aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/perf_event.h2
-rw-r--r--kernel/events/core.c2
-rw-r--r--tools/arch/arm64/include/uapi/asm/unistd.h1
-rw-r--r--tools/arch/powerpc/include/uapi/asm/kvm.h1
-rw-r--r--tools/arch/s390/include/uapi/asm/kvm.h2
-rw-r--r--tools/arch/x86/include/uapi/asm/kvm.h6
-rw-r--r--tools/include/uapi/asm-generic/unistd.h2
-rw-r--r--tools/include/uapi/linux/fs.h393
-rw-r--r--tools/include/uapi/linux/if_link.h1
-rw-r--r--tools/include/uapi/linux/kvm.h21
-rw-r--r--tools/include/uapi/linux/mman.h2
-rw-r--r--tools/include/uapi/linux/netlink.h1
-rw-r--r--tools/include/uapi/linux/perf_event.h2
-rw-r--r--tools/include/uapi/sound/asound.h2
-rw-r--r--tools/lib/subcmd/parse-options.c19
-rw-r--r--tools/lib/subcmd/parse-options.h2
-rw-r--r--tools/perf/Documentation/build-xed.txt19
-rw-r--r--tools/perf/Documentation/intel-pt.txt2
-rw-r--r--tools/perf/Documentation/itrace.txt7
-rw-r--r--tools/perf/Documentation/perf-script.txt18
-rw-r--r--tools/perf/Documentation/perf-top.txt10
-rw-r--r--tools/perf/Documentation/perf-trace.txt67
-rw-r--r--tools/perf/Makefile.perf19
-rwxr-xr-xtools/perf/arch/arm64/entry/syscalls/mksyscalltbl2
-rw-r--r--tools/perf/arch/sparc/Makefile2
-rw-r--r--tools/perf/arch/sparc/annotate/instructions.c169
-rw-r--r--tools/perf/builtin-record.c24
-rw-r--r--tools/perf/builtin-script.c166
-rw-r--r--tools/perf/builtin-stat.c24
-rw-r--r--tools/perf/builtin-top.c21
-rw-r--r--tools/perf/builtin-trace.c98
-rwxr-xr-xtools/perf/check-headers.sh1
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/scripts/python/call-graph-from-sql.py339
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py2
-rw-r--r--tools/perf/scripts/python/export-to-sqlite.py2
-rwxr-xr-xtools/perf/scripts/python/exported-sql-viewer.py2128
-rw-r--r--tools/perf/trace/beauty/Build1
-rw-r--r--tools/perf/trace/beauty/beauty.h7
-rw-r--r--tools/perf/trace/beauty/clone.c3
-rwxr-xr-xtools/perf/trace/beauty/drm_ioctl.sh1
-rw-r--r--tools/perf/trace/beauty/eventfd.c2
-rw-r--r--tools/perf/trace/beauty/fcntl.c3
-rw-r--r--tools/perf/trace/beauty/flock.c2
-rw-r--r--tools/perf/trace/beauty/futex_op.c2
-rw-r--r--tools/perf/trace/beauty/futex_val3.c2
-rw-r--r--tools/perf/trace/beauty/ioctl.c3
-rw-r--r--tools/perf/trace/beauty/kcmp.c3
-rwxr-xr-xtools/perf/trace/beauty/kcmp_type.sh1
-rwxr-xr-xtools/perf/trace/beauty/kvm_ioctl.sh1
-rwxr-xr-xtools/perf/trace/beauty/madvise_behavior.sh1
-rw-r--r--tools/perf/trace/beauty/mmap.c50
-rwxr-xr-xtools/perf/trace/beauty/mmap_flags.sh32
-rw-r--r--tools/perf/trace/beauty/mode_t.c2
-rw-r--r--tools/perf/trace/beauty/mount_flags.c43
-rwxr-xr-xtools/perf/trace/beauty/mount_flags.sh15
-rw-r--r--tools/perf/trace/beauty/msg_flags.c2
-rw-r--r--tools/perf/trace/beauty/open_flags.c2
-rw-r--r--tools/perf/trace/beauty/perf_event_open.c2
-rwxr-xr-xtools/perf/trace/beauty/perf_ioctl.sh1
-rw-r--r--tools/perf/trace/beauty/pid.c3
-rw-r--r--tools/perf/trace/beauty/pkey_alloc.c30
-rwxr-xr-xtools/perf/trace/beauty/pkey_alloc_access_rights.sh1
-rw-r--r--tools/perf/trace/beauty/prctl.c3
-rwxr-xr-xtools/perf/trace/beauty/prctl_option.sh1
-rw-r--r--tools/perf/trace/beauty/sched_policy.c2
-rw-r--r--tools/perf/trace/beauty/seccomp.c2
-rw-r--r--tools/perf/trace/beauty/signum.c2
-rwxr-xr-xtools/perf/trace/beauty/sndrv_ctl_ioctl.sh1
-rwxr-xr-xtools/perf/trace/beauty/sndrv_pcm_ioctl.sh1
-rw-r--r--tools/perf/trace/beauty/sockaddr.c2
-rw-r--r--tools/perf/trace/beauty/socket.c2
-rwxr-xr-xtools/perf/trace/beauty/socket_ipproto.sh1
-rw-r--r--tools/perf/trace/beauty/socket_type.c2
-rw-r--r--tools/perf/trace/beauty/statx.c3
-rwxr-xr-xtools/perf/trace/beauty/vhost_virtio_ioctl.sh1
-rw-r--r--tools/perf/trace/beauty/waitid_options.c2
-rw-r--r--tools/perf/util/annotate.c8
-rw-r--r--tools/perf/util/auxtrace.c17
-rw-r--r--tools/perf/util/auxtrace.h5
-rw-r--r--tools/perf/util/cs-etm.c42
-rw-r--r--tools/perf/util/env.h1
-rw-r--r--tools/perf/util/event.c1
-rw-r--r--tools/perf/util/evlist.c2
-rw-r--r--tools/perf/util/evsel.c27
-rw-r--r--tools/perf/util/evsel.h5
-rw-r--r--tools/perf/util/genelf.h6
-rw-r--r--tools/perf/util/header.c23
-rw-r--r--tools/perf/util/header.h1
-rw-r--r--tools/perf/util/intel-bts.c20
-rw-r--r--tools/perf/util/intel-pt.c31
-rw-r--r--tools/perf/util/machine.c54
-rw-r--r--tools/perf/util/parse-events.c8
-rw-r--r--tools/perf/util/parse-events.h1
-rw-r--r--tools/perf/util/parse-events.l1
-rw-r--r--tools/perf/util/symbol-elf.c12
-rw-r--r--tools/perf/util/symbol.h3
-rw-r--r--tools/perf/util/thread-stack.c44
-rw-r--r--tools/perf/util/thread-stack.h2
-rw-r--r--tools/perf/util/thread.c13
-rw-r--r--tools/perf/util/thread.h4
-rw-r--r--tools/perf/util/unwind-libdw.c4
102 files changed, 3616 insertions, 539 deletions
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index f35eb72739c0..9de8780ac8d9 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -646,10 +646,12 @@ struct perf_event_mmap_page {
646 * 646 *
647 * PERF_RECORD_MISC_MMAP_DATA - PERF_RECORD_MMAP* events 647 * PERF_RECORD_MISC_MMAP_DATA - PERF_RECORD_MMAP* events
648 * PERF_RECORD_MISC_COMM_EXEC - PERF_RECORD_COMM event 648 * PERF_RECORD_MISC_COMM_EXEC - PERF_RECORD_COMM event
649 * PERF_RECORD_MISC_FORK_EXEC - PERF_RECORD_FORK event (perf internal)
649 * PERF_RECORD_MISC_SWITCH_OUT - PERF_RECORD_SWITCH* events 650 * PERF_RECORD_MISC_SWITCH_OUT - PERF_RECORD_SWITCH* events
650 */ 651 */
651#define PERF_RECORD_MISC_MMAP_DATA (1 << 13) 652#define PERF_RECORD_MISC_MMAP_DATA (1 << 13)
652#define PERF_RECORD_MISC_COMM_EXEC (1 << 13) 653#define PERF_RECORD_MISC_COMM_EXEC (1 << 13)
654#define PERF_RECORD_MISC_FORK_EXEC (1 << 13)
653#define PERF_RECORD_MISC_SWITCH_OUT (1 << 13) 655#define PERF_RECORD_MISC_SWITCH_OUT (1 << 13)
654/* 656/*
655 * These PERF_RECORD_MISC_* flags below are safely reused 657 * These PERF_RECORD_MISC_* flags below are safely reused
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 8c490130c4fb..84530ab358c3 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -750,7 +750,7 @@ static inline void update_cgrp_time_from_event(struct perf_event *event)
750 /* 750 /*
751 * Do not update time when cgroup is not active 751 * Do not update time when cgroup is not active
752 */ 752 */
753 if (cgroup_is_descendant(cgrp->css.cgroup, event->cgrp->css.cgroup)) 753 if (cgroup_is_descendant(cgrp->css.cgroup, event->cgrp->css.cgroup))
754 __update_cgrp_time(event->cgrp); 754 __update_cgrp_time(event->cgrp);
755} 755}
756 756
diff --git a/tools/arch/arm64/include/uapi/asm/unistd.h b/tools/arch/arm64/include/uapi/asm/unistd.h
index 5072cbd15c82..dae1584cf017 100644
--- a/tools/arch/arm64/include/uapi/asm/unistd.h
+++ b/tools/arch/arm64/include/uapi/asm/unistd.h
@@ -16,5 +16,6 @@
16 */ 16 */
17 17
18#define __ARCH_WANT_RENAMEAT 18#define __ARCH_WANT_RENAMEAT
19#define __ARCH_WANT_NEW_STAT
19 20
20#include <asm-generic/unistd.h> 21#include <asm-generic/unistd.h>
diff --git a/tools/arch/powerpc/include/uapi/asm/kvm.h b/tools/arch/powerpc/include/uapi/asm/kvm.h
index 1b32b56a03d3..8c876c166ef2 100644
--- a/tools/arch/powerpc/include/uapi/asm/kvm.h
+++ b/tools/arch/powerpc/include/uapi/asm/kvm.h
@@ -634,6 +634,7 @@ struct kvm_ppc_cpu_char {
634 634
635#define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe) 635#define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe)
636#define KVM_REG_PPC_ONLINE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbf) 636#define KVM_REG_PPC_ONLINE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbf)
637#define KVM_REG_PPC_PTCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc0)
637 638
638/* Transactional Memory checkpointed state: 639/* Transactional Memory checkpointed state:
639 * This is all GPRs, all VSX regs and a subset of SPRs 640 * This is all GPRs, all VSX regs and a subset of SPRs
diff --git a/tools/arch/s390/include/uapi/asm/kvm.h b/tools/arch/s390/include/uapi/asm/kvm.h
index 9a50f02b9894..16511d97e8dc 100644
--- a/tools/arch/s390/include/uapi/asm/kvm.h
+++ b/tools/arch/s390/include/uapi/asm/kvm.h
@@ -160,6 +160,8 @@ struct kvm_s390_vm_cpu_subfunc {
160#define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1 160#define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1
161#define KVM_S390_VM_CRYPTO_DISABLE_AES_KW 2 161#define KVM_S390_VM_CRYPTO_DISABLE_AES_KW 2
162#define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW 3 162#define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW 3
163#define KVM_S390_VM_CRYPTO_ENABLE_APIE 4
164#define KVM_S390_VM_CRYPTO_DISABLE_APIE 5
163 165
164/* kvm attributes for migration mode */ 166/* kvm attributes for migration mode */
165#define KVM_S390_VM_MIGRATION_STOP 0 167#define KVM_S390_VM_MIGRATION_STOP 0
diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h
index 8a6eff9c27f3..dabfcf7c3941 100644
--- a/tools/arch/x86/include/uapi/asm/kvm.h
+++ b/tools/arch/x86/include/uapi/asm/kvm.h
@@ -300,10 +300,7 @@ struct kvm_vcpu_events {
300 __u8 injected; 300 __u8 injected;
301 __u8 nr; 301 __u8 nr;
302 __u8 has_error_code; 302 __u8 has_error_code;
303 union { 303 __u8 pending;
304 __u8 pad;
305 __u8 pending;
306 };
307 __u32 error_code; 304 __u32 error_code;
308 } exception; 305 } exception;
309 struct { 306 struct {
@@ -387,6 +384,7 @@ struct kvm_sync_regs {
387 384
388#define KVM_STATE_NESTED_GUEST_MODE 0x00000001 385#define KVM_STATE_NESTED_GUEST_MODE 0x00000001
389#define KVM_STATE_NESTED_RUN_PENDING 0x00000002 386#define KVM_STATE_NESTED_RUN_PENDING 0x00000002
387#define KVM_STATE_NESTED_EVMCS 0x00000004
390 388
391#define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001 389#define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001
392#define KVM_STATE_NESTED_SMM_VMXON 0x00000002 390#define KVM_STATE_NESTED_SMM_VMXON 0x00000002
diff --git a/tools/include/uapi/asm-generic/unistd.h b/tools/include/uapi/asm-generic/unistd.h
index df4bedb9b01c..538546edbfbd 100644
--- a/tools/include/uapi/asm-generic/unistd.h
+++ b/tools/include/uapi/asm-generic/unistd.h
@@ -242,10 +242,12 @@ __SYSCALL(__NR_tee, sys_tee)
242/* fs/stat.c */ 242/* fs/stat.c */
243#define __NR_readlinkat 78 243#define __NR_readlinkat 78
244__SYSCALL(__NR_readlinkat, sys_readlinkat) 244__SYSCALL(__NR_readlinkat, sys_readlinkat)
245#if defined(__ARCH_WANT_NEW_STAT) || defined(__ARCH_WANT_STAT64)
245#define __NR3264_fstatat 79 246#define __NR3264_fstatat 79
246__SC_3264(__NR3264_fstatat, sys_fstatat64, sys_newfstatat) 247__SC_3264(__NR3264_fstatat, sys_fstatat64, sys_newfstatat)
247#define __NR3264_fstat 80 248#define __NR3264_fstat 80
248__SC_3264(__NR3264_fstat, sys_fstat64, sys_newfstat) 249__SC_3264(__NR3264_fstat, sys_fstat64, sys_newfstat)
250#endif
249 251
250/* fs/sync.c */ 252/* fs/sync.c */
251#define __NR_sync 81 253#define __NR_sync 81
diff --git a/tools/include/uapi/linux/fs.h b/tools/include/uapi/linux/fs.h
new file mode 100644
index 000000000000..a441ea1bfe6d
--- /dev/null
+++ b/tools/include/uapi/linux/fs.h
@@ -0,0 +1,393 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef _UAPI_LINUX_FS_H
3#define _UAPI_LINUX_FS_H
4
5/*
6 * This file has definitions for some important file table structures
7 * and constants and structures used by various generic file system
8 * ioctl's. Please do not make any changes in this file before
9 * sending patches for review to linux-fsdevel@vger.kernel.org and
10 * linux-api@vger.kernel.org.
11 */
12
13#include <linux/limits.h>
14#include <linux/ioctl.h>
15#include <linux/types.h>
16
17/*
18 * It's silly to have NR_OPEN bigger than NR_FILE, but you can change
19 * the file limit at runtime and only root can increase the per-process
20 * nr_file rlimit, so it's safe to set up a ridiculously high absolute
21 * upper limit on files-per-process.
22 *
23 * Some programs (notably those using select()) may have to be
24 * recompiled to take full advantage of the new limits..
25 */
26
27/* Fixed constants first: */
28#undef NR_OPEN
29#define INR_OPEN_CUR 1024 /* Initial setting for nfile rlimits */
30#define INR_OPEN_MAX 4096 /* Hard limit for nfile rlimits */
31
32#define BLOCK_SIZE_BITS 10
33#define BLOCK_SIZE (1<<BLOCK_SIZE_BITS)
34
35#define SEEK_SET 0 /* seek relative to beginning of file */
36#define SEEK_CUR 1 /* seek relative to current file position */
37#define SEEK_END 2 /* seek relative to end of file */
38#define SEEK_DATA 3 /* seek to the next data */
39#define SEEK_HOLE 4 /* seek to the next hole */
40#define SEEK_MAX SEEK_HOLE
41
42#define RENAME_NOREPLACE (1 << 0) /* Don't overwrite target */
43#define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */
44#define RENAME_WHITEOUT (1 << 2) /* Whiteout source */
45
46struct file_clone_range {
47 __s64 src_fd;
48 __u64 src_offset;
49 __u64 src_length;
50 __u64 dest_offset;
51};
52
53struct fstrim_range {
54 __u64 start;
55 __u64 len;
56 __u64 minlen;
57};
58
59/* extent-same (dedupe) ioctls; these MUST match the btrfs ioctl definitions */
60#define FILE_DEDUPE_RANGE_SAME 0
61#define FILE_DEDUPE_RANGE_DIFFERS 1
62
63/* from struct btrfs_ioctl_file_extent_same_info */
64struct file_dedupe_range_info {
65 __s64 dest_fd; /* in - destination file */
66 __u64 dest_offset; /* in - start of extent in destination */
67 __u64 bytes_deduped; /* out - total # of bytes we were able
68 * to dedupe from this file. */
69 /* status of this dedupe operation:
70 * < 0 for error
71 * == FILE_DEDUPE_RANGE_SAME if dedupe succeeds
72 * == FILE_DEDUPE_RANGE_DIFFERS if data differs
73 */
74 __s32 status; /* out - see above description */
75 __u32 reserved; /* must be zero */
76};
77
78/* from struct btrfs_ioctl_file_extent_same_args */
79struct file_dedupe_range {
80 __u64 src_offset; /* in - start of extent in source */
81 __u64 src_length; /* in - length of extent */
82 __u16 dest_count; /* in - total elements in info array */
83 __u16 reserved1; /* must be zero */
84 __u32 reserved2; /* must be zero */
85 struct file_dedupe_range_info info[0];
86};
87
88/* And dynamically-tunable limits and defaults: */
89struct files_stat_struct {
90 unsigned long nr_files; /* read only */
91 unsigned long nr_free_files; /* read only */
92 unsigned long max_files; /* tunable */
93};
94
95struct inodes_stat_t {
96 long nr_inodes;
97 long nr_unused;
98 long dummy[5]; /* padding for sysctl ABI compatibility */
99};
100
101
102#define NR_FILE 8192 /* this can well be larger on a larger system */
103
104
105/*
106 * These are the fs-independent mount-flags: up to 32 flags are supported
107 */
108#define MS_RDONLY 1 /* Mount read-only */
109#define MS_NOSUID 2 /* Ignore suid and sgid bits */
110#define MS_NODEV 4 /* Disallow access to device special files */
111#define MS_NOEXEC 8 /* Disallow program execution */
112#define MS_SYNCHRONOUS 16 /* Writes are synced at once */
113#define MS_REMOUNT 32 /* Alter flags of a mounted FS */
114#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */
115#define MS_DIRSYNC 128 /* Directory modifications are synchronous */
116#define MS_NOATIME 1024 /* Do not update access times. */
117#define MS_NODIRATIME 2048 /* Do not update directory access times */
118#define MS_BIND 4096
119#define MS_MOVE 8192
120#define MS_REC 16384
121#define MS_VERBOSE 32768 /* War is peace. Verbosity is silence.
122 MS_VERBOSE is deprecated. */
123#define MS_SILENT 32768
124#define MS_POSIXACL (1<<16) /* VFS does not apply the umask */
125#define MS_UNBINDABLE (1<<17) /* change to unbindable */
126#define MS_PRIVATE (1<<18) /* change to private */
127#define MS_SLAVE (1<<19) /* change to slave */
128#define MS_SHARED (1<<20) /* change to shared */
129#define MS_RELATIME (1<<21) /* Update atime relative to mtime/ctime. */
130#define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */
131#define MS_I_VERSION (1<<23) /* Update inode I_version field */
132#define MS_STRICTATIME (1<<24) /* Always perform atime updates */
133#define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */
134
135/* These sb flags are internal to the kernel */
136#define MS_SUBMOUNT (1<<26)
137#define MS_NOREMOTELOCK (1<<27)
138#define MS_NOSEC (1<<28)
139#define MS_BORN (1<<29)
140#define MS_ACTIVE (1<<30)
141#define MS_NOUSER (1<<31)
142
143/*
144 * Superblock flags that can be altered by MS_REMOUNT
145 */
146#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|\
147 MS_LAZYTIME)
148
149/*
150 * Old magic mount flag and mask
151 */
152#define MS_MGC_VAL 0xC0ED0000
153#define MS_MGC_MSK 0xffff0000
154
155/*
156 * Structure for FS_IOC_FSGETXATTR[A] and FS_IOC_FSSETXATTR.
157 */
158struct fsxattr {
159 __u32 fsx_xflags; /* xflags field value (get/set) */
160 __u32 fsx_extsize; /* extsize field value (get/set)*/
161 __u32 fsx_nextents; /* nextents field value (get) */
162 __u32 fsx_projid; /* project identifier (get/set) */
163 __u32 fsx_cowextsize; /* CoW extsize field value (get/set)*/
164 unsigned char fsx_pad[8];
165};
166
167/*
168 * Flags for the fsx_xflags field
169 */
170#define FS_XFLAG_REALTIME 0x00000001 /* data in realtime volume */
171#define FS_XFLAG_PREALLOC 0x00000002 /* preallocated file extents */
172#define FS_XFLAG_IMMUTABLE 0x00000008 /* file cannot be modified */
173#define FS_XFLAG_APPEND 0x00000010 /* all writes append */
174#define FS_XFLAG_SYNC 0x00000020 /* all writes synchronous */
175#define FS_XFLAG_NOATIME 0x00000040 /* do not update access time */
176#define FS_XFLAG_NODUMP 0x00000080 /* do not include in backups */
177#define FS_XFLAG_RTINHERIT 0x00000100 /* create with rt bit set */
178#define FS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */
179#define FS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */
180#define FS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */
181#define FS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */
182#define FS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */
183#define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */
184#define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */
185#define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */
186#define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */
187
188/* the read-only stuff doesn't really belong here, but any other place is
189 probably as bad and I don't want to create yet another include file. */
190
191#define BLKROSET _IO(0x12,93) /* set device read-only (0 = read-write) */
192#define BLKROGET _IO(0x12,94) /* get read-only status (0 = read_write) */
193#define BLKRRPART _IO(0x12,95) /* re-read partition table */
194#define BLKGETSIZE _IO(0x12,96) /* return device size /512 (long *arg) */
195#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
196#define BLKRASET _IO(0x12,98) /* set read ahead for block device */
197#define BLKRAGET _IO(0x12,99) /* get current read ahead setting */
198#define BLKFRASET _IO(0x12,100)/* set filesystem (mm/filemap.c) read-ahead */
199#define BLKFRAGET _IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */
200#define BLKSECTSET _IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */
201#define BLKSECTGET _IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
202#define BLKSSZGET _IO(0x12,104)/* get block device sector size */
203#if 0
204#define BLKPG _IO(0x12,105)/* See blkpg.h */
205
206/* Some people are morons. Do not use sizeof! */
207
208#define BLKELVGET _IOR(0x12,106,size_t)/* elevator get */
209#define BLKELVSET _IOW(0x12,107,size_t)/* elevator set */
210/* This was here just to show that the number is taken -
211 probably all these _IO(0x12,*) ioctls should be moved to blkpg.h. */
212#endif
213/* A jump here: 108-111 have been used for various private purposes. */
214#define BLKBSZGET _IOR(0x12,112,size_t)
215#define BLKBSZSET _IOW(0x12,113,size_t)
216#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
217#define BLKTRACESETUP _IOWR(0x12,115,struct blk_user_trace_setup)
218#define BLKTRACESTART _IO(0x12,116)
219#define BLKTRACESTOP _IO(0x12,117)
220#define BLKTRACETEARDOWN _IO(0x12,118)
221#define BLKDISCARD _IO(0x12,119)
222#define BLKIOMIN _IO(0x12,120)
223#define BLKIOOPT _IO(0x12,121)
224#define BLKALIGNOFF _IO(0x12,122)
225#define BLKPBSZGET _IO(0x12,123)
226#define BLKDISCARDZEROES _IO(0x12,124)
227#define BLKSECDISCARD _IO(0x12,125)
228#define BLKROTATIONAL _IO(0x12,126)
229#define BLKZEROOUT _IO(0x12,127)
230/*
231 * A jump here: 130-131 are reserved for zoned block devices
232 * (see uapi/linux/blkzoned.h)
233 */
234
235#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
236#define FIBMAP _IO(0x00,1) /* bmap access */
237#define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */
238#define FIFREEZE _IOWR('X', 119, int) /* Freeze */
239#define FITHAW _IOWR('X', 120, int) /* Thaw */
240#define FITRIM _IOWR('X', 121, struct fstrim_range) /* Trim */
241#define FICLONE _IOW(0x94, 9, int)
242#define FICLONERANGE _IOW(0x94, 13, struct file_clone_range)
243#define FIDEDUPERANGE _IOWR(0x94, 54, struct file_dedupe_range)
244
245#define FSLABEL_MAX 256 /* Max chars for the interface; each fs may differ */
246
247#define FS_IOC_GETFLAGS _IOR('f', 1, long)
248#define FS_IOC_SETFLAGS _IOW('f', 2, long)
249#define FS_IOC_GETVERSION _IOR('v', 1, long)
250#define FS_IOC_SETVERSION _IOW('v', 2, long)
251#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap)
252#define FS_IOC32_GETFLAGS _IOR('f', 1, int)
253#define FS_IOC32_SETFLAGS _IOW('f', 2, int)
254#define FS_IOC32_GETVERSION _IOR('v', 1, int)
255#define FS_IOC32_SETVERSION _IOW('v', 2, int)
256#define FS_IOC_FSGETXATTR _IOR('X', 31, struct fsxattr)
257#define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr)
258#define FS_IOC_GETFSLABEL _IOR(0x94, 49, char[FSLABEL_MAX])
259#define FS_IOC_SETFSLABEL _IOW(0x94, 50, char[FSLABEL_MAX])
260
261/*
262 * File system encryption support
263 */
264/* Policy provided via an ioctl on the topmost directory */
265#define FS_KEY_DESCRIPTOR_SIZE 8
266
267#define FS_POLICY_FLAGS_PAD_4 0x00
268#define FS_POLICY_FLAGS_PAD_8 0x01
269#define FS_POLICY_FLAGS_PAD_16 0x02
270#define FS_POLICY_FLAGS_PAD_32 0x03
271#define FS_POLICY_FLAGS_PAD_MASK 0x03
272#define FS_POLICY_FLAGS_VALID 0x03
273
274/* Encryption algorithms */
275#define FS_ENCRYPTION_MODE_INVALID 0
276#define FS_ENCRYPTION_MODE_AES_256_XTS 1
277#define FS_ENCRYPTION_MODE_AES_256_GCM 2
278#define FS_ENCRYPTION_MODE_AES_256_CBC 3
279#define FS_ENCRYPTION_MODE_AES_256_CTS 4
280#define FS_ENCRYPTION_MODE_AES_128_CBC 5
281#define FS_ENCRYPTION_MODE_AES_128_CTS 6
282#define FS_ENCRYPTION_MODE_SPECK128_256_XTS 7 /* Removed, do not use. */
283#define FS_ENCRYPTION_MODE_SPECK128_256_CTS 8 /* Removed, do not use. */
284
285struct fscrypt_policy {
286 __u8 version;
287 __u8 contents_encryption_mode;
288 __u8 filenames_encryption_mode;
289 __u8 flags;
290 __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
291};
292
293#define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy)
294#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16])
295#define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy)
296
297/* Parameters for passing an encryption key into the kernel keyring */
298#define FS_KEY_DESC_PREFIX "fscrypt:"
299#define FS_KEY_DESC_PREFIX_SIZE 8
300
301/* Structure that userspace passes to the kernel keyring */
302#define FS_MAX_KEY_SIZE 64
303
304struct fscrypt_key {
305 __u32 mode;
306 __u8 raw[FS_MAX_KEY_SIZE];
307 __u32 size;
308};
309
310/*
311 * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)
312 *
313 * Note: for historical reasons, these flags were originally used and
314 * defined for use by ext2/ext3, and then other file systems started
315 * using these flags so they wouldn't need to write their own version
316 * of chattr/lsattr (which was shipped as part of e2fsprogs). You
317 * should think twice before trying to use these flags in new
318 * contexts, or trying to assign these flags, since they are used both
319 * as the UAPI and the on-disk encoding for ext2/3/4. Also, we are
320 * almost out of 32-bit flags. :-)
321 *
322 * We have recently hoisted FS_IOC_FSGETXATTR / FS_IOC_FSSETXATTR from
323 * XFS to the generic FS level interface. This uses a structure that
324 * has padding and hence has more room to grow, so it may be more
325 * appropriate for many new use cases.
326 *
327 * Please do not change these flags or interfaces before checking with
328 * linux-fsdevel@vger.kernel.org and linux-api@vger.kernel.org.
329 */
330#define FS_SECRM_FL 0x00000001 /* Secure deletion */
331#define FS_UNRM_FL 0x00000002 /* Undelete */
332#define FS_COMPR_FL 0x00000004 /* Compress file */
333#define FS_SYNC_FL 0x00000008 /* Synchronous updates */
334#define FS_IMMUTABLE_FL 0x00000010 /* Immutable file */
335#define FS_APPEND_FL 0x00000020 /* writes to file may only append */
336#define FS_NODUMP_FL 0x00000040 /* do not dump file */
337#define FS_NOATIME_FL 0x00000080 /* do not update atime */
338/* Reserved for compression usage... */
339#define FS_DIRTY_FL 0x00000100
340#define FS_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
341#define FS_NOCOMP_FL 0x00000400 /* Don't compress */
342/* End compression flags --- maybe not all used */
343#define FS_ENCRYPT_FL 0x00000800 /* Encrypted file */
344#define FS_BTREE_FL 0x00001000 /* btree format dir */
345#define FS_INDEX_FL 0x00001000 /* hash-indexed directory */
346#define FS_IMAGIC_FL 0x00002000 /* AFS directory */
347#define FS_JOURNAL_DATA_FL 0x00004000 /* Reserved for ext3 */
348#define FS_NOTAIL_FL 0x00008000 /* file tail should not be merged */
349#define FS_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
350#define FS_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
351#define FS_HUGE_FILE_FL 0x00040000 /* Reserved for ext4 */
352#define FS_EXTENT_FL 0x00080000 /* Extents */
353#define FS_EA_INODE_FL 0x00200000 /* Inode used for large EA */
354#define FS_EOFBLOCKS_FL 0x00400000 /* Reserved for ext4 */
355#define FS_NOCOW_FL 0x00800000 /* Do not cow file */
356#define FS_INLINE_DATA_FL 0x10000000 /* Reserved for ext4 */
357#define FS_PROJINHERIT_FL 0x20000000 /* Create with parents projid */
358#define FS_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
359
360#define FS_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
361#define FS_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */
362
363
364#define SYNC_FILE_RANGE_WAIT_BEFORE 1
365#define SYNC_FILE_RANGE_WRITE 2
366#define SYNC_FILE_RANGE_WAIT_AFTER 4
367
368/*
369 * Flags for preadv2/pwritev2:
370 */
371
372typedef int __bitwise __kernel_rwf_t;
373
374/* high priority request, poll if possible */
375#define RWF_HIPRI ((__force __kernel_rwf_t)0x00000001)
376
377/* per-IO O_DSYNC */
378#define RWF_DSYNC ((__force __kernel_rwf_t)0x00000002)
379
380/* per-IO O_SYNC */
381#define RWF_SYNC ((__force __kernel_rwf_t)0x00000004)
382
383/* per-IO, return -EAGAIN if operation would block */
384#define RWF_NOWAIT ((__force __kernel_rwf_t)0x00000008)
385
386/* per-IO O_APPEND */
387#define RWF_APPEND ((__force __kernel_rwf_t)0x00000010)
388
389/* mask of flags supported by the kernel */
390#define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT |\
391 RWF_APPEND)
392
393#endif /* _UAPI_LINUX_FS_H */
diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h
index 58faab897201..1debfa42cba1 100644
--- a/tools/include/uapi/linux/if_link.h
+++ b/tools/include/uapi/linux/if_link.h
@@ -287,6 +287,7 @@ enum {
287 IFLA_BR_MCAST_STATS_ENABLED, 287 IFLA_BR_MCAST_STATS_ENABLED,
288 IFLA_BR_MCAST_IGMP_VERSION, 288 IFLA_BR_MCAST_IGMP_VERSION,
289 IFLA_BR_MCAST_MLD_VERSION, 289 IFLA_BR_MCAST_MLD_VERSION,
290 IFLA_BR_VLAN_STATS_PER_PORT,
290 __IFLA_BR_MAX, 291 __IFLA_BR_MAX,
291}; 292};
292 293
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
index 2875ce85b322..2b7a652c9fa4 100644
--- a/tools/include/uapi/linux/kvm.h
+++ b/tools/include/uapi/linux/kvm.h
@@ -420,13 +420,19 @@ struct kvm_run {
420struct kvm_coalesced_mmio_zone { 420struct kvm_coalesced_mmio_zone {
421 __u64 addr; 421 __u64 addr;
422 __u32 size; 422 __u32 size;
423 __u32 pad; 423 union {
424 __u32 pad;
425 __u32 pio;
426 };
424}; 427};
425 428
426struct kvm_coalesced_mmio { 429struct kvm_coalesced_mmio {
427 __u64 phys_addr; 430 __u64 phys_addr;
428 __u32 len; 431 __u32 len;
429 __u32 pad; 432 union {
433 __u32 pad;
434 __u32 pio;
435 };
430 __u8 data[8]; 436 __u8 data[8];
431}; 437};
432 438
@@ -752,6 +758,15 @@ struct kvm_ppc_resize_hpt {
752#define KVM_S390_SIE_PAGE_OFFSET 1 758#define KVM_S390_SIE_PAGE_OFFSET 1
753 759
754/* 760/*
761 * On arm64, machine type can be used to request the physical
762 * address size for the VM. Bits[7-0] are reserved for the guest
763 * PA size shift (i.e, log2(PA_Size)). For backward compatibility,
764 * value 0 implies the default IPA size, 40bits.
765 */
766#define KVM_VM_TYPE_ARM_IPA_SIZE_MASK 0xffULL
767#define KVM_VM_TYPE_ARM_IPA_SIZE(x) \
768 ((x) & KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
769/*
755 * ioctls for /dev/kvm fds: 770 * ioctls for /dev/kvm fds:
756 */ 771 */
757#define KVM_GET_API_VERSION _IO(KVMIO, 0x00) 772#define KVM_GET_API_VERSION _IO(KVMIO, 0x00)
@@ -958,6 +973,8 @@ struct kvm_ppc_resize_hpt {
958#define KVM_CAP_HYPERV_SEND_IPI 161 973#define KVM_CAP_HYPERV_SEND_IPI 161
959#define KVM_CAP_COALESCED_PIO 162 974#define KVM_CAP_COALESCED_PIO 162
960#define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163 975#define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163
976#define KVM_CAP_EXCEPTION_PAYLOAD 164
977#define KVM_CAP_ARM_VM_IPA_SIZE 165
961 978
962#ifdef KVM_CAP_IRQ_ROUTING 979#ifdef KVM_CAP_IRQ_ROUTING
963 980
diff --git a/tools/include/uapi/linux/mman.h b/tools/include/uapi/linux/mman.h
index bfd5938fede6..d0f515d53299 100644
--- a/tools/include/uapi/linux/mman.h
+++ b/tools/include/uapi/linux/mman.h
@@ -28,7 +28,9 @@
28#define MAP_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB 28#define MAP_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB
29#define MAP_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB 29#define MAP_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB
30#define MAP_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB 30#define MAP_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB
31#define MAP_HUGE_32MB HUGETLB_FLAG_ENCODE_32MB
31#define MAP_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB 32#define MAP_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB
33#define MAP_HUGE_512MB HUGETLB_FLAG_ENCODE_512MB
32#define MAP_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB 34#define MAP_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB
33#define MAP_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB 35#define MAP_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB
34#define MAP_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB 36#define MAP_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB
diff --git a/tools/include/uapi/linux/netlink.h b/tools/include/uapi/linux/netlink.h
index 776bc92e9118..486ed1f0c0bc 100644
--- a/tools/include/uapi/linux/netlink.h
+++ b/tools/include/uapi/linux/netlink.h
@@ -155,6 +155,7 @@ enum nlmsgerr_attrs {
155#define NETLINK_LIST_MEMBERSHIPS 9 155#define NETLINK_LIST_MEMBERSHIPS 9
156#define NETLINK_CAP_ACK 10 156#define NETLINK_CAP_ACK 10
157#define NETLINK_EXT_ACK 11 157#define NETLINK_EXT_ACK 11
158#define NETLINK_DUMP_STRICT_CHK 12
158 159
159struct nl_pktinfo { 160struct nl_pktinfo {
160 __u32 group; 161 __u32 group;
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index f35eb72739c0..9de8780ac8d9 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -646,10 +646,12 @@ struct perf_event_mmap_page {
646 * 646 *
647 * PERF_RECORD_MISC_MMAP_DATA - PERF_RECORD_MMAP* events 647 * PERF_RECORD_MISC_MMAP_DATA - PERF_RECORD_MMAP* events
648 * PERF_RECORD_MISC_COMM_EXEC - PERF_RECORD_COMM event 648 * PERF_RECORD_MISC_COMM_EXEC - PERF_RECORD_COMM event
649 * PERF_RECORD_MISC_FORK_EXEC - PERF_RECORD_FORK event (perf internal)
649 * PERF_RECORD_MISC_SWITCH_OUT - PERF_RECORD_SWITCH* events 650 * PERF_RECORD_MISC_SWITCH_OUT - PERF_RECORD_SWITCH* events
650 */ 651 */
651#define PERF_RECORD_MISC_MMAP_DATA (1 << 13) 652#define PERF_RECORD_MISC_MMAP_DATA (1 << 13)
652#define PERF_RECORD_MISC_COMM_EXEC (1 << 13) 653#define PERF_RECORD_MISC_COMM_EXEC (1 << 13)
654#define PERF_RECORD_MISC_FORK_EXEC (1 << 13)
653#define PERF_RECORD_MISC_SWITCH_OUT (1 << 13) 655#define PERF_RECORD_MISC_SWITCH_OUT (1 << 13)
654/* 656/*
655 * These PERF_RECORD_MISC_* flags below are safely reused 657 * These PERF_RECORD_MISC_* flags below are safely reused
diff --git a/tools/include/uapi/sound/asound.h b/tools/include/uapi/sound/asound.h
index ed0a120d4f08..404d4b9ffe76 100644
--- a/tools/include/uapi/sound/asound.h
+++ b/tools/include/uapi/sound/asound.h
@@ -752,7 +752,7 @@ struct snd_timer_info {
752#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */ 752#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */
753 753
754struct snd_timer_params { 754struct snd_timer_params {
755 unsigned int flags; /* flags - SNDRV_MIXER_PSFLG_* */ 755 unsigned int flags; /* flags - SNDRV_TIMER_PSFLG_* */
756 unsigned int ticks; /* requested resolution in ticks */ 756 unsigned int ticks; /* requested resolution in ticks */
757 unsigned int queue_size; /* total size of queue (32-1024) */ 757 unsigned int queue_size; /* total size of queue (32-1024) */
758 unsigned int reserved0; /* reserved, was: failure locations */ 758 unsigned int reserved0; /* reserved, was: failure locations */
diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c
index cb7154eccbdc..dbb9efbf718a 100644
--- a/tools/lib/subcmd/parse-options.c
+++ b/tools/lib/subcmd/parse-options.c
@@ -116,6 +116,7 @@ static int get_value(struct parse_opt_ctx_t *p,
116 case OPTION_INTEGER: 116 case OPTION_INTEGER:
117 case OPTION_UINTEGER: 117 case OPTION_UINTEGER:
118 case OPTION_LONG: 118 case OPTION_LONG:
119 case OPTION_ULONG:
119 case OPTION_U64: 120 case OPTION_U64:
120 default: 121 default:
121 break; 122 break;
@@ -166,6 +167,7 @@ static int get_value(struct parse_opt_ctx_t *p,
166 case OPTION_INTEGER: 167 case OPTION_INTEGER:
167 case OPTION_UINTEGER: 168 case OPTION_UINTEGER:
168 case OPTION_LONG: 169 case OPTION_LONG:
170 case OPTION_ULONG:
169 case OPTION_U64: 171 case OPTION_U64:
170 default: 172 default:
171 break; 173 break;
@@ -295,6 +297,22 @@ static int get_value(struct parse_opt_ctx_t *p,
295 return opterror(opt, "expects a numerical value", flags); 297 return opterror(opt, "expects a numerical value", flags);
296 return 0; 298 return 0;
297 299
300 case OPTION_ULONG:
301 if (unset) {
302 *(unsigned long *)opt->value = 0;
303 return 0;
304 }
305 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
306 *(unsigned long *)opt->value = opt->defval;
307 return 0;
308 }
309 if (get_arg(p, opt, flags, &arg))
310 return -1;
311 *(unsigned long *)opt->value = strtoul(arg, (char **)&s, 10);
312 if (*s)
313 return opterror(opt, "expects a numerical value", flags);
314 return 0;
315
298 case OPTION_U64: 316 case OPTION_U64:
299 if (unset) { 317 if (unset) {
300 *(u64 *)opt->value = 0; 318 *(u64 *)opt->value = 0;
@@ -703,6 +721,7 @@ static void print_option_help(const struct option *opts, int full)
703 case OPTION_ARGUMENT: 721 case OPTION_ARGUMENT:
704 break; 722 break;
705 case OPTION_LONG: 723 case OPTION_LONG:
724 case OPTION_ULONG:
706 case OPTION_U64: 725 case OPTION_U64:
707 case OPTION_INTEGER: 726 case OPTION_INTEGER:
708 case OPTION_UINTEGER: 727 case OPTION_UINTEGER:
diff --git a/tools/lib/subcmd/parse-options.h b/tools/lib/subcmd/parse-options.h
index 92fdbe1519f6..6ca2a8bfe716 100644
--- a/tools/lib/subcmd/parse-options.h
+++ b/tools/lib/subcmd/parse-options.h
@@ -25,6 +25,7 @@ enum parse_opt_type {
25 OPTION_STRING, 25 OPTION_STRING,
26 OPTION_INTEGER, 26 OPTION_INTEGER,
27 OPTION_LONG, 27 OPTION_LONG,
28 OPTION_ULONG,
28 OPTION_CALLBACK, 29 OPTION_CALLBACK,
29 OPTION_U64, 30 OPTION_U64,
30 OPTION_UINTEGER, 31 OPTION_UINTEGER,
@@ -133,6 +134,7 @@ struct option {
133#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } 134#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) }
134#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) } 135#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) }
135#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } 136#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
137#define OPT_ULONG(s, l, v, h) { .type = OPTION_ULONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned long *), .help = (h) }
136#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } 138#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
137#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), .argh = (a), .help = (h) } 139#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), .argh = (a), .help = (h) }
138#define OPT_STRING_OPTARG(s, l, v, a, h, d) \ 140#define OPT_STRING_OPTARG(s, l, v, a, h, d) \
diff --git a/tools/perf/Documentation/build-xed.txt b/tools/perf/Documentation/build-xed.txt
new file mode 100644
index 000000000000..6222c1e7231f
--- /dev/null
+++ b/tools/perf/Documentation/build-xed.txt
@@ -0,0 +1,19 @@
1
2For --xed the xed tool is needed. Here is how to install it:
3
4 $ git clone https://github.com/intelxed/mbuild.git mbuild
5 $ git clone https://github.com/intelxed/xed
6 $ cd xed
7 $ ./mfile.py --share
8 $ ./mfile.py examples
9 $ sudo ./mfile.py --prefix=/usr/local install
10 $ sudo ldconfig
11 $ sudo cp obj/examples/xed /usr/local/bin
12
13Basic xed testing:
14
15 $ xed | head -3
16 ERROR: required argument(s) were missing
17 Copyright (C) 2017, Intel Corporation. All rights reserved.
18 XED version: [v10.0-328-g7d62c8c49b7b]
19 $
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index 76971d2e4164..115eaacc455f 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -106,7 +106,7 @@ in transaction, respectively.
106While it is possible to create scripts to analyze the data, an alternative 106While it is possible to create scripts to analyze the data, an alternative
107approach is available to export the data to a sqlite or postgresql database. 107approach is available to export the data to a sqlite or postgresql database.
108Refer to script export-to-sqlite.py or export-to-postgresql.py for more details, 108Refer to script export-to-sqlite.py or export-to-postgresql.py for more details,
109and to script call-graph-from-sql.py for an example of using the database. 109and to script exported-sql-viewer.py for an example of using the database.
110 110
111There is also script intel-pt-events.py which provides an example of how to 111There is also script intel-pt-events.py which provides an example of how to
112unpack the raw data for power events and PTWRITE. 112unpack the raw data for power events and PTWRITE.
diff --git a/tools/perf/Documentation/itrace.txt b/tools/perf/Documentation/itrace.txt
index a3abe04c779d..c2182cbabde3 100644
--- a/tools/perf/Documentation/itrace.txt
+++ b/tools/perf/Documentation/itrace.txt
@@ -11,10 +11,11 @@
11 l synthesize last branch entries (use with i or x) 11 l synthesize last branch entries (use with i or x)
12 s skip initial number of events 12 s skip initial number of events
13 13
14 The default is all events i.e. the same as --itrace=ibxwpe 14 The default is all events i.e. the same as --itrace=ibxwpe,
15 except for perf script where it is --itrace=ce
15 16
16 In addition, the period (default 100000) for instructions events 17 In addition, the period (default 100000, except for perf script where it is 1)
17 can be specified in units of: 18 for instructions events can be specified in units of:
18 19
19 i instructions 20 i instructions
20 t ticks 21 t ticks
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index afdafe2110a1..a2b37ce48094 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -383,6 +383,24 @@ include::itrace.txt[]
383 will be printed. Each entry has function name and file/line. Enabled by 383 will be printed. Each entry has function name and file/line. Enabled by
384 default, disable with --no-inline. 384 default, disable with --no-inline.
385 385
386--insn-trace::
387 Show instruction stream for intel_pt traces. Combine with --xed to
388 show disassembly.
389
390--xed::
391 Run xed disassembler on output. Requires installing the xed disassembler.
392
393--call-trace::
394 Show call stream for intel_pt traces. The CPUs are interleaved, but
395 can be filtered with -C.
396
397--call-ret-trace::
398 Show call and return stream for intel_pt traces.
399
400--graph-function::
401 For itrace only show specified functions and their callees for
402 itrace. Multiple functions can be separated by comma.
403
386SEE ALSO 404SEE ALSO
387-------- 405--------
388linkperf:perf-record[1], linkperf:perf-script-perl[1], 406linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 114fda12aa49..808b664343c9 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -242,6 +242,16 @@ Default is to monitor all CPUS.
242--hierarchy:: 242--hierarchy::
243 Enable hierarchy output. 243 Enable hierarchy output.
244 244
245--overwrite::
246 Enable this to use just the most recent records, which helps in high core count
247 machines such as Knights Landing/Mill, but right now is disabled by default as
248 the pausing used in this technique is leading to loss of metadata events such
249 as PERF_RECORD_MMAP which makes 'perf top' unable to resolve samples, leading
250 to lots of unknown samples appearing on the UI. Enable this if you are in such
251 machines and profiling a workload that doesn't creates short lived threads and/or
252 doesn't uses many executable mmap operations. Work is being planed to solve
253 this situation, till then, this will remain disabled by default.
254
245--force:: 255--force::
246 Don't do ownership validation. 256 Don't do ownership validation.
247 257
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 115db9e06ecd..e113450503d2 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -171,6 +171,11 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
171--kernel-syscall-graph:: 171--kernel-syscall-graph::
172 Show the kernel callchains on the syscall exit path. 172 Show the kernel callchains on the syscall exit path.
173 173
174--max-events=N::
175 Stop after processing N events. Note that strace-like events are considered
176 only at exit time or when a syscall is interrupted, i.e. in those cases this
177 option is equivalent to the number of lines printed.
178
174--max-stack:: 179--max-stack::
175 Set the stack depth limit when parsing the callchain, anything 180 Set the stack depth limit when parsing the callchain, anything
176 beyond the specified depth will be ignored. Note that at this point 181 beyond the specified depth will be ignored. Note that at this point
@@ -238,6 +243,68 @@ Trace syscalls, major and minor pagefaults:
238 As you can see, there was major pagefault in python process, from 243 As you can see, there was major pagefault in python process, from
239 CRYPTO_push_info_ routine which faulted somewhere in libcrypto.so. 244 CRYPTO_push_info_ routine which faulted somewhere in libcrypto.so.
240 245
246Trace the first 4 open, openat or open_by_handle_at syscalls (in the future more syscalls may match here):
247
248 $ perf trace -e open* --max-events 4
249 [root@jouet perf]# trace -e open* --max-events 4
250 2272.992 ( 0.037 ms): gnome-shell/1370 openat(dfd: CWD, filename: /proc/self/stat) = 31
251 2277.481 ( 0.139 ms): gnome-shell/3039 openat(dfd: CWD, filename: /proc/self/stat) = 65
252 3026.398 ( 0.076 ms): gnome-shell/3039 openat(dfd: CWD, filename: /proc/self/stat) = 65
253 4294.665 ( 0.015 ms): sed/15879 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) = 3
254 $
255
256Trace the first minor page fault when running a workload:
257
258 # perf trace -F min --max-stack=7 --max-events 1 sleep 1
259 0.000 ( 0.000 ms): sleep/18006 minfault [__clear_user+0x1a] => 0x5626efa56080 (?k)
260 __clear_user ([kernel.kallsyms])
261 load_elf_binary ([kernel.kallsyms])
262 search_binary_handler ([kernel.kallsyms])
263 __do_execve_file.isra.33 ([kernel.kallsyms])
264 __x64_sys_execve ([kernel.kallsyms])
265 do_syscall_64 ([kernel.kallsyms])
266 entry_SYSCALL_64 ([kernel.kallsyms])
267 #
268
269Trace the next min page page fault to take place on the first CPU:
270
271 # perf trace -F min --call-graph=dwarf --max-events 1 --cpu 0
272 0.000 ( 0.000 ms): Web Content/17136 minfault [js::gc::Chunk::fetchNextDecommittedArena+0x4b] => 0x7fbe6181b000 (?.)
273 js::gc::FreeSpan::initAsEmpty (inlined)
274 js::gc::Arena::setAsNotAllocated (inlined)
275 js::gc::Chunk::fetchNextDecommittedArena (/usr/lib64/firefox/libxul.so)
276 js::gc::Chunk::allocateArena (/usr/lib64/firefox/libxul.so)
277 js::gc::GCRuntime::allocateArena (/usr/lib64/firefox/libxul.so)
278 js::gc::ArenaLists::allocateFromArena (/usr/lib64/firefox/libxul.so)
279 js::gc::GCRuntime::tryNewTenuredThing<JSString, (js::AllowGC)1> (inlined)
280 js::AllocateString<JSString, (js::AllowGC)1> (/usr/lib64/firefox/libxul.so)
281 js::Allocate<JSThinInlineString, (js::AllowGC)1> (inlined)
282 JSThinInlineString::new_<(js::AllowGC)1> (inlined)
283 AllocateInlineString<(js::AllowGC)1, unsigned char> (inlined)
284 js::ConcatStrings<(js::AllowGC)1> (/usr/lib64/firefox/libxul.so)
285 [0x18b26e6bc2bd] (/tmp/perf-17136.map)
286 #
287
288Trace the next two sched:sched_switch events, four block:*_plug events, the
289next block:*_unplug and the next three net:*dev_queue events, this last one
290with a backtrace of at most 16 entries, system wide:
291
292 # perf trace -e sched:*switch/nr=2/,block:*_plug/nr=4/,block:*_unplug/nr=1/,net:*dev_queue/nr=3,max-stack=16/
293 0.000 :0/0 sched:sched_switch:swapper/2:0 [120] S ==> rcu_sched:10 [120]
294 0.015 rcu_sched/10 sched:sched_switch:rcu_sched:10 [120] R ==> swapper/2:0 [120]
295 254.198 irq/50-iwlwifi/680 net:net_dev_queue:dev=wlp3s0 skbaddr=0xffff93498051f600 len=66
296 __dev_queue_xmit ([kernel.kallsyms])
297 273.977 :0/0 net:net_dev_queue:dev=wlp3s0 skbaddr=0xffff93498051f600 len=78
298 __dev_queue_xmit ([kernel.kallsyms])
299 274.007 :0/0 net:net_dev_queue:dev=wlp3s0 skbaddr=0xffff93498051ff00 len=78
300 __dev_queue_xmit ([kernel.kallsyms])
301 2930.140 kworker/u16:58/2722 block:block_plug:[kworker/u16:58]
302 2930.162 kworker/u16:58/2722 block:block_unplug:[kworker/u16:58] 1
303 4466.094 jbd2/dm-2-8/748 block:block_plug:[jbd2/dm-2-8]
304 8050.123 kworker/u16:30/2694 block:block_plug:[kworker/u16:30]
305 8050.271 kworker/u16:30/2694 block:block_plug:[kworker/u16:30]
306 #
307
241SEE ALSO 308SEE ALSO
242-------- 309--------
243linkperf:perf-record[1], linkperf:perf-script[1] 310linkperf:perf-record[1], linkperf:perf-script[1]
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 2f3bf025e305..3ccb4f0bf088 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -1,4 +1,5 @@
1include ../scripts/Makefile.include 1include ../scripts/Makefile.include
2include ../scripts/Makefile.arch
2 3
3# The default target of this Makefile is... 4# The default target of this Makefile is...
4all: 5all:
@@ -385,6 +386,8 @@ export INSTALL SHELL_PATH
385SHELL = $(SHELL_PATH) 386SHELL = $(SHELL_PATH)
386 387
387linux_uapi_dir := $(srctree)/tools/include/uapi/linux 388linux_uapi_dir := $(srctree)/tools/include/uapi/linux
389asm_generic_uapi_dir := $(srctree)/tools/include/uapi/asm-generic
390arch_asm_uapi_dir := $(srctree)/tools/arch/$(ARCH)/include/uapi/asm/
388 391
389beauty_outdir := $(OUTPUT)trace/beauty/generated 392beauty_outdir := $(OUTPUT)trace/beauty/generated
390beauty_ioctl_outdir := $(beauty_outdir)/ioctl 393beauty_ioctl_outdir := $(beauty_outdir)/ioctl
@@ -460,6 +463,18 @@ madvise_behavior_tbl := $(srctree)/tools/perf/trace/beauty/madvise_behavior.sh
460$(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl) 463$(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl)
461 $(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@ 464 $(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@
462 465
466mmap_flags_array := $(beauty_outdir)/mmap_flags_array.c
467mmap_flags_tbl := $(srctree)/tools/perf/trace/beauty/mmap_flags.sh
468
469$(mmap_flags_array): $(asm_generic_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman-common.h $(arch_asm_uapi_dir)/mman.h $(mmap_flags_tbl)
470 $(Q)$(SHELL) '$(mmap_flags_tbl)' $(asm_generic_uapi_dir) $(arch_asm_uapi_dir) > $@
471
472mount_flags_array := $(beauty_outdir)/mount_flags_array.c
473mount_flags_tbl := $(srctree)/tools/perf/trace/beauty/mount_flags.sh
474
475$(mount_flags_array): $(linux_uapi_dir)/fs.h $(mount_flags_tbl)
476 $(Q)$(SHELL) '$(mount_flags_tbl)' $(linux_uapi_dir) > $@
477
463prctl_option_array := $(beauty_outdir)/prctl_option_array.c 478prctl_option_array := $(beauty_outdir)/prctl_option_array.c
464prctl_hdr_dir := $(srctree)/tools/include/uapi/linux/ 479prctl_hdr_dir := $(srctree)/tools/include/uapi/linux/
465prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh 480prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh
@@ -577,6 +592,8 @@ prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioc
577 $(socket_ipproto_array) \ 592 $(socket_ipproto_array) \
578 $(vhost_virtio_ioctl_array) \ 593 $(vhost_virtio_ioctl_array) \
579 $(madvise_behavior_array) \ 594 $(madvise_behavior_array) \
595 $(mmap_flags_array) \
596 $(mount_flags_array) \
580 $(perf_ioctl_array) \ 597 $(perf_ioctl_array) \
581 $(prctl_option_array) \ 598 $(prctl_option_array) \
582 $(arch_errno_name_array) 599 $(arch_errno_name_array)
@@ -863,6 +880,8 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
863 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \ 880 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
864 $(OUTPUT)pmu-events/pmu-events.c \ 881 $(OUTPUT)pmu-events/pmu-events.c \
865 $(OUTPUT)$(madvise_behavior_array) \ 882 $(OUTPUT)$(madvise_behavior_array) \
883 $(OUTPUT)$(mmap_flags_array) \
884 $(OUTPUT)$(mount_flags_array) \
866 $(OUTPUT)$(drm_ioctl_array) \ 885 $(OUTPUT)$(drm_ioctl_array) \
867 $(OUTPUT)$(pkey_alloc_access_rights_array) \ 886 $(OUTPUT)$(pkey_alloc_access_rights_array) \
868 $(OUTPUT)$(sndrv_ctl_ioctl_array) \ 887 $(OUTPUT)$(sndrv_ctl_ioctl_array) \
diff --git a/tools/perf/arch/arm64/entry/syscalls/mksyscalltbl b/tools/perf/arch/arm64/entry/syscalls/mksyscalltbl
index 2dbb8cade048..c88fd32563eb 100755
--- a/tools/perf/arch/arm64/entry/syscalls/mksyscalltbl
+++ b/tools/perf/arch/arm64/entry/syscalls/mksyscalltbl
@@ -23,7 +23,7 @@ create_table_from_c()
23{ 23{
24 local sc nr last_sc 24 local sc nr last_sc
25 25
26 create_table_exe=`mktemp /tmp/create-table-XXXXXX` 26 create_table_exe=`mktemp ${TMPDIR:-/tmp}/create-table-XXXXXX`
27 27
28 { 28 {
29 29
diff --git a/tools/perf/arch/sparc/Makefile b/tools/perf/arch/sparc/Makefile
index 7fbca175099e..275dea7ff59a 100644
--- a/tools/perf/arch/sparc/Makefile
+++ b/tools/perf/arch/sparc/Makefile
@@ -1,3 +1,5 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3endif 3endif
4
5PERF_HAVE_JITDUMP := 1
diff --git a/tools/perf/arch/sparc/annotate/instructions.c b/tools/perf/arch/sparc/annotate/instructions.c
new file mode 100644
index 000000000000..2614c010c235
--- /dev/null
+++ b/tools/perf/arch/sparc/annotate/instructions.c
@@ -0,0 +1,169 @@
1// SPDX-License-Identifier: GPL-2.0
2
3static int is_branch_cond(const char *cond)
4{
5 if (cond[0] == '\0')
6 return 1;
7
8 if (cond[0] == 'a' && cond[1] == '\0')
9 return 1;
10
11 if (cond[0] == 'c' &&
12 (cond[1] == 'c' || cond[1] == 's') &&
13 cond[2] == '\0')
14 return 1;
15
16 if (cond[0] == 'e' &&
17 (cond[1] == '\0' ||
18 (cond[1] == 'q' && cond[2] == '\0')))
19 return 1;
20
21 if (cond[0] == 'g' &&
22 (cond[1] == '\0' ||
23 (cond[1] == 't' && cond[2] == '\0') ||
24 (cond[1] == 'e' && cond[2] == '\0') ||
25 (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
26 return 1;
27
28 if (cond[0] == 'l' &&
29 (cond[1] == '\0' ||
30 (cond[1] == 't' && cond[2] == '\0') ||
31 (cond[1] == 'u' && cond[2] == '\0') ||
32 (cond[1] == 'e' && cond[2] == '\0') ||
33 (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
34 return 1;
35
36 if (cond[0] == 'n' &&
37 (cond[1] == '\0' ||
38 (cond[1] == 'e' && cond[2] == '\0') ||
39 (cond[1] == 'z' && cond[2] == '\0') ||
40 (cond[1] == 'e' && cond[2] == 'g' && cond[3] == '\0')))
41 return 1;
42
43 if (cond[0] == 'b' &&
44 cond[1] == 'p' &&
45 cond[2] == 'o' &&
46 cond[3] == 's' &&
47 cond[4] == '\0')
48 return 1;
49
50 if (cond[0] == 'v' &&
51 (cond[1] == 'c' || cond[1] == 's') &&
52 cond[2] == '\0')
53 return 1;
54
55 if (cond[0] == 'b' &&
56 cond[1] == 'z' &&
57 cond[2] == '\0')
58 return 1;
59
60 return 0;
61}
62
63static int is_branch_reg_cond(const char *cond)
64{
65 if ((cond[0] == 'n' || cond[0] == 'l') &&
66 cond[1] == 'z' &&
67 cond[2] == '\0')
68 return 1;
69
70 if (cond[0] == 'z' &&
71 cond[1] == '\0')
72 return 1;
73
74 if ((cond[0] == 'g' || cond[0] == 'l') &&
75 cond[1] == 'e' &&
76 cond[2] == 'z' &&
77 cond[3] == '\0')
78 return 1;
79
80 if (cond[0] == 'g' &&
81 cond[1] == 'z' &&
82 cond[2] == '\0')
83 return 1;
84
85 return 0;
86}
87
88static int is_branch_float_cond(const char *cond)
89{
90 if (cond[0] == '\0')
91 return 1;
92
93 if ((cond[0] == 'a' || cond[0] == 'e' ||
94 cond[0] == 'z' || cond[0] == 'g' ||
95 cond[0] == 'l' || cond[0] == 'n' ||
96 cond[0] == 'o' || cond[0] == 'u') &&
97 cond[1] == '\0')
98 return 1;
99
100 if (((cond[0] == 'g' && cond[1] == 'e') ||
101 (cond[0] == 'l' && (cond[1] == 'e' ||
102 cond[1] == 'g')) ||
103 (cond[0] == 'n' && (cond[1] == 'e' ||
104 cond[1] == 'z')) ||
105 (cond[0] == 'u' && (cond[1] == 'e' ||
106 cond[1] == 'g' ||
107 cond[1] == 'l'))) &&
108 cond[2] == '\0')
109 return 1;
110
111 if (cond[0] == 'u' &&
112 (cond[1] == 'g' || cond[1] == 'l') &&
113 cond[2] == 'e' &&
114 cond[3] == '\0')
115 return 1;
116
117 return 0;
118}
119
120static struct ins_ops *sparc__associate_instruction_ops(struct arch *arch, const char *name)
121{
122 struct ins_ops *ops = NULL;
123
124 if (!strcmp(name, "call") ||
125 !strcmp(name, "jmp") ||
126 !strcmp(name, "jmpl")) {
127 ops = &call_ops;
128 } else if (!strcmp(name, "ret") ||
129 !strcmp(name, "retl") ||
130 !strcmp(name, "return")) {
131 ops = &ret_ops;
132 } else if (!strcmp(name, "mov")) {
133 ops = &mov_ops;
134 } else {
135 if (name[0] == 'c' &&
136 (name[1] == 'w' || name[1] == 'x'))
137 name += 2;
138
139 if (name[0] == 'b') {
140 const char *cond = name + 1;
141
142 if (cond[0] == 'r') {
143 if (is_branch_reg_cond(cond + 1))
144 ops = &jump_ops;
145 } else if (is_branch_cond(cond)) {
146 ops = &jump_ops;
147 }
148 } else if (name[0] == 'f' && name[1] == 'b') {
149 if (is_branch_float_cond(name + 2))
150 ops = &jump_ops;
151 }
152 }
153
154 if (ops)
155 arch__associate_ins_ops(arch, name, ops);
156
157 return ops;
158}
159
160static int sparc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
161{
162 if (!arch->initialized) {
163 arch->initialized = true;
164 arch->associate_instruction_ops = sparc__associate_instruction_ops;
165 arch->objdump.comment_char = '#';
166 }
167
168 return 0;
169}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0980dfe3396b..10cf889c6d75 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -592,6 +592,9 @@ static void record__init_features(struct record *rec)
592 if (!rec->opts.full_auxtrace) 592 if (!rec->opts.full_auxtrace)
593 perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 593 perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
594 594
595 if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns))
596 perf_header__clear_feat(&session->header, HEADER_CLOCKID);
597
595 perf_header__clear_feat(&session->header, HEADER_STAT); 598 perf_header__clear_feat(&session->header, HEADER_STAT);
596} 599}
597 600
@@ -897,6 +900,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
897 900
898 record__init_features(rec); 901 record__init_features(rec);
899 902
903 if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
904 session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
905
900 if (forks) { 906 if (forks) {
901 err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 907 err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
902 argv, data->is_pipe, 908 argv, data->is_pipe,
@@ -1337,6 +1343,19 @@ static const struct clockid_map clockids[] = {
1337 CLOCKID_END, 1343 CLOCKID_END,
1338}; 1344};
1339 1345
1346static int get_clockid_res(clockid_t clk_id, u64 *res_ns)
1347{
1348 struct timespec res;
1349
1350 *res_ns = 0;
1351 if (!clock_getres(clk_id, &res))
1352 *res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
1353 else
1354 pr_warning("WARNING: Failed to determine specified clock resolution.\n");
1355
1356 return 0;
1357}
1358
1340static int parse_clockid(const struct option *opt, const char *str, int unset) 1359static int parse_clockid(const struct option *opt, const char *str, int unset)
1341{ 1360{
1342 struct record_opts *opts = (struct record_opts *)opt->value; 1361 struct record_opts *opts = (struct record_opts *)opt->value;
@@ -1360,7 +1379,7 @@ static int parse_clockid(const struct option *opt, const char *str, int unset)
1360 1379
1361 /* if its a number, we're done */ 1380 /* if its a number, we're done */
1362 if (sscanf(str, "%d", &opts->clockid) == 1) 1381 if (sscanf(str, "%d", &opts->clockid) == 1)
1363 return 0; 1382 return get_clockid_res(opts->clockid, &opts->clockid_res_ns);
1364 1383
1365 /* allow a "CLOCK_" prefix to the name */ 1384 /* allow a "CLOCK_" prefix to the name */
1366 if (!strncasecmp(str, "CLOCK_", 6)) 1385 if (!strncasecmp(str, "CLOCK_", 6))
@@ -1369,7 +1388,8 @@ static int parse_clockid(const struct option *opt, const char *str, int unset)
1369 for (cm = clockids; cm->name; cm++) { 1388 for (cm = clockids; cm->name; cm++) {
1370 if (!strcasecmp(str, cm->name)) { 1389 if (!strcasecmp(str, cm->name)) {
1371 opts->clockid = cm->clockid; 1390 opts->clockid = cm->clockid;
1372 return 0; 1391 return get_clockid_res(opts->clockid,
1392 &opts->clockid_res_ns);
1373 } 1393 }
1374 } 1394 }
1375 1395
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 4da5e32b9e03..b5bc85bd0bbe 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -44,6 +44,7 @@
44#include <sys/stat.h> 44#include <sys/stat.h>
45#include <fcntl.h> 45#include <fcntl.h>
46#include <unistd.h> 46#include <unistd.h>
47#include <subcmd/pager.h>
47 48
48#include "sane_ctype.h" 49#include "sane_ctype.h"
49 50
@@ -912,7 +913,7 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,
912 913
913static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en, 914static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
914 struct perf_insn *x, u8 *inbuf, int len, 915 struct perf_insn *x, u8 *inbuf, int len,
915 int insn, FILE *fp) 916 int insn, FILE *fp, int *total_cycles)
916{ 917{
917 int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", ip, 918 int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", ip,
918 dump_insn(x, ip, inbuf, len, NULL), 919 dump_insn(x, ip, inbuf, len, NULL),
@@ -921,7 +922,8 @@ static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
921 en->flags.in_tx ? " INTX" : "", 922 en->flags.in_tx ? " INTX" : "",
922 en->flags.abort ? " ABORT" : ""); 923 en->flags.abort ? " ABORT" : "");
923 if (en->flags.cycles) { 924 if (en->flags.cycles) {
924 printed += fprintf(fp, " %d cycles", en->flags.cycles); 925 *total_cycles += en->flags.cycles;
926 printed += fprintf(fp, " %d cycles [%d]", en->flags.cycles, *total_cycles);
925 if (insn) 927 if (insn)
926 printed += fprintf(fp, " %.2f IPC", (float)insn / en->flags.cycles); 928 printed += fprintf(fp, " %.2f IPC", (float)insn / en->flags.cycles);
927 } 929 }
@@ -978,6 +980,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
978 u8 buffer[MAXBB]; 980 u8 buffer[MAXBB];
979 unsigned off; 981 unsigned off;
980 struct symbol *lastsym = NULL; 982 struct symbol *lastsym = NULL;
983 int total_cycles = 0;
981 984
982 if (!(br && br->nr)) 985 if (!(br && br->nr))
983 return 0; 986 return 0;
@@ -998,7 +1001,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
998 printed += ip__fprintf_sym(br->entries[nr - 1].from, thread, 1001 printed += ip__fprintf_sym(br->entries[nr - 1].from, thread,
999 x.cpumode, x.cpu, &lastsym, attr, fp); 1002 x.cpumode, x.cpu, &lastsym, attr, fp);
1000 printed += ip__fprintf_jump(br->entries[nr - 1].from, &br->entries[nr - 1], 1003 printed += ip__fprintf_jump(br->entries[nr - 1].from, &br->entries[nr - 1],
1001 &x, buffer, len, 0, fp); 1004 &x, buffer, len, 0, fp, &total_cycles);
1002 } 1005 }
1003 1006
1004 /* Print all blocks */ 1007 /* Print all blocks */
@@ -1026,7 +1029,8 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
1026 1029
1027 printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp); 1030 printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
1028 if (ip == end) { 1031 if (ip == end) {
1029 printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp); 1032 printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp,
1033 &total_cycles);
1030 break; 1034 break;
1031 } else { 1035 } else {
1032 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip, 1036 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip,
@@ -1104,6 +1108,35 @@ out:
1104 return printed; 1108 return printed;
1105} 1109}
1106 1110
1111static const char *resolve_branch_sym(struct perf_sample *sample,
1112 struct perf_evsel *evsel,
1113 struct thread *thread,
1114 struct addr_location *al,
1115 u64 *ip)
1116{
1117 struct addr_location addr_al;
1118 struct perf_event_attr *attr = &evsel->attr;
1119 const char *name = NULL;
1120
1121 if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
1122 if (sample_addr_correlates_sym(attr)) {
1123 thread__resolve(thread, &addr_al, sample);
1124 if (addr_al.sym)
1125 name = addr_al.sym->name;
1126 else
1127 *ip = sample->addr;
1128 } else {
1129 *ip = sample->addr;
1130 }
1131 } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
1132 if (al->sym)
1133 name = al->sym->name;
1134 else
1135 *ip = sample->ip;
1136 }
1137 return name;
1138}
1139
1107static int perf_sample__fprintf_callindent(struct perf_sample *sample, 1140static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1108 struct perf_evsel *evsel, 1141 struct perf_evsel *evsel,
1109 struct thread *thread, 1142 struct thread *thread,
@@ -1111,7 +1144,6 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1111{ 1144{
1112 struct perf_event_attr *attr = &evsel->attr; 1145 struct perf_event_attr *attr = &evsel->attr;
1113 size_t depth = thread_stack__depth(thread); 1146 size_t depth = thread_stack__depth(thread);
1114 struct addr_location addr_al;
1115 const char *name = NULL; 1147 const char *name = NULL;
1116 static int spacing; 1148 static int spacing;
1117 int len = 0; 1149 int len = 0;
@@ -1125,22 +1157,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1125 if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN) 1157 if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN)
1126 depth += 1; 1158 depth += 1;
1127 1159
1128 if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) { 1160 name = resolve_branch_sym(sample, evsel, thread, al, &ip);
1129 if (sample_addr_correlates_sym(attr)) {
1130 thread__resolve(thread, &addr_al, sample);
1131 if (addr_al.sym)
1132 name = addr_al.sym->name;
1133 else
1134 ip = sample->addr;
1135 } else {
1136 ip = sample->addr;
1137 }
1138 } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
1139 if (al->sym)
1140 name = al->sym->name;
1141 else
1142 ip = sample->ip;
1143 }
1144 1161
1145 if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) { 1162 if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) {
1146 dlen += fprintf(fp, "("); 1163 dlen += fprintf(fp, "(");
@@ -1646,6 +1663,47 @@ static void perf_sample__fprint_metric(struct perf_script *script,
1646 } 1663 }
1647} 1664}
1648 1665
1666static bool show_event(struct perf_sample *sample,
1667 struct perf_evsel *evsel,
1668 struct thread *thread,
1669 struct addr_location *al)
1670{
1671 int depth = thread_stack__depth(thread);
1672
1673 if (!symbol_conf.graph_function)
1674 return true;
1675
1676 if (thread->filter) {
1677 if (depth <= thread->filter_entry_depth) {
1678 thread->filter = false;
1679 return false;
1680 }
1681 return true;
1682 } else {
1683 const char *s = symbol_conf.graph_function;
1684 u64 ip;
1685 const char *name = resolve_branch_sym(sample, evsel, thread, al,
1686 &ip);
1687 unsigned nlen;
1688
1689 if (!name)
1690 return false;
1691 nlen = strlen(name);
1692 while (*s) {
1693 unsigned len = strcspn(s, ",");
1694 if (nlen == len && !strncmp(name, s, len)) {
1695 thread->filter = true;
1696 thread->filter_entry_depth = depth;
1697 return true;
1698 }
1699 s += len;
1700 if (*s == ',')
1701 s++;
1702 }
1703 return false;
1704 }
1705}
1706
1649static void process_event(struct perf_script *script, 1707static void process_event(struct perf_script *script,
1650 struct perf_sample *sample, struct perf_evsel *evsel, 1708 struct perf_sample *sample, struct perf_evsel *evsel,
1651 struct addr_location *al, 1709 struct addr_location *al,
@@ -1660,6 +1718,9 @@ static void process_event(struct perf_script *script,
1660 if (output[type].fields == 0) 1718 if (output[type].fields == 0)
1661 return; 1719 return;
1662 1720
1721 if (!show_event(sample, evsel, thread, al))
1722 return;
1723
1663 ++es->samples; 1724 ++es->samples;
1664 1725
1665 perf_sample__fprintf_start(sample, thread, evsel, 1726 perf_sample__fprintf_start(sample, thread, evsel,
@@ -1737,6 +1798,9 @@ static void process_event(struct perf_script *script,
1737 1798
1738 if (PRINT_FIELD(METRIC)) 1799 if (PRINT_FIELD(METRIC))
1739 perf_sample__fprint_metric(script, thread, evsel, sample, fp); 1800 perf_sample__fprint_metric(script, thread, evsel, sample, fp);
1801
1802 if (verbose)
1803 fflush(fp);
1740} 1804}
1741 1805
1742static struct scripting_ops *scripting_ops; 1806static struct scripting_ops *scripting_ops;
@@ -3100,6 +3164,44 @@ static int perf_script__process_auxtrace_info(struct perf_session *session,
3100#define perf_script__process_auxtrace_info 0 3164#define perf_script__process_auxtrace_info 0
3101#endif 3165#endif
3102 3166
3167static int parse_insn_trace(const struct option *opt __maybe_unused,
3168 const char *str __maybe_unused,
3169 int unset __maybe_unused)
3170{
3171 parse_output_fields(NULL, "+insn,-event,-period", 0);
3172 itrace_parse_synth_opts(opt, "i0ns", 0);
3173 nanosecs = true;
3174 return 0;
3175}
3176
3177static int parse_xed(const struct option *opt __maybe_unused,
3178 const char *str __maybe_unused,
3179 int unset __maybe_unused)
3180{
3181 force_pager("xed -F insn: -A -64 | less");
3182 return 0;
3183}
3184
3185static int parse_call_trace(const struct option *opt __maybe_unused,
3186 const char *str __maybe_unused,
3187 int unset __maybe_unused)
3188{
3189 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent", 0);
3190 itrace_parse_synth_opts(opt, "cewp", 0);
3191 nanosecs = true;
3192 return 0;
3193}
3194
3195static int parse_callret_trace(const struct option *opt __maybe_unused,
3196 const char *str __maybe_unused,
3197 int unset __maybe_unused)
3198{
3199 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent,+flags", 0);
3200 itrace_parse_synth_opts(opt, "crewp", 0);
3201 nanosecs = true;
3202 return 0;
3203}
3204
3103int cmd_script(int argc, const char **argv) 3205int cmd_script(int argc, const char **argv)
3104{ 3206{
3105 bool show_full_info = false; 3207 bool show_full_info = false;
@@ -3109,7 +3211,10 @@ int cmd_script(int argc, const char **argv)
3109 char *rec_script_path = NULL; 3211 char *rec_script_path = NULL;
3110 char *rep_script_path = NULL; 3212 char *rep_script_path = NULL;
3111 struct perf_session *session; 3213 struct perf_session *session;
3112 struct itrace_synth_opts itrace_synth_opts = { .set = false, }; 3214 struct itrace_synth_opts itrace_synth_opts = {
3215 .set = false,
3216 .default_no_sample = true,
3217 };
3113 char *script_path = NULL; 3218 char *script_path = NULL;
3114 const char **__argv; 3219 const char **__argv;
3115 int i, j, err = 0; 3220 int i, j, err = 0;
@@ -3184,6 +3289,16 @@ int cmd_script(int argc, const char **argv)
3184 "system-wide collection from all CPUs"), 3289 "system-wide collection from all CPUs"),
3185 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 3290 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
3186 "only consider these symbols"), 3291 "only consider these symbols"),
3292 OPT_CALLBACK_OPTARG(0, "insn-trace", &itrace_synth_opts, NULL, NULL,
3293 "Decode instructions from itrace", parse_insn_trace),
3294 OPT_CALLBACK_OPTARG(0, "xed", NULL, NULL, NULL,
3295 "Run xed disassembler on output", parse_xed),
3296 OPT_CALLBACK_OPTARG(0, "call-trace", &itrace_synth_opts, NULL, NULL,
3297 "Decode calls from from itrace", parse_call_trace),
3298 OPT_CALLBACK_OPTARG(0, "call-ret-trace", &itrace_synth_opts, NULL, NULL,
3299 "Decode calls and returns from itrace", parse_callret_trace),
3300 OPT_STRING(0, "graph-function", &symbol_conf.graph_function, "symbol[,symbol...]",
3301 "Only print symbols and callees with --call-trace/--call-ret-trace"),
3187 OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]", 3302 OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]",
3188 "Stop display of callgraph at these symbols"), 3303 "Stop display of callgraph at these symbols"),
3189 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 3304 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
@@ -3417,8 +3532,10 @@ int cmd_script(int argc, const char **argv)
3417 exit(-1); 3532 exit(-1);
3418 } 3533 }
3419 3534
3420 if (!script_name) 3535 if (!script_name) {
3421 setup_pager(); 3536 setup_pager();
3537 use_browser = 0;
3538 }
3422 3539
3423 session = perf_session__new(&data, false, &script.tool); 3540 session = perf_session__new(&data, false, &script.tool);
3424 if (session == NULL) 3541 if (session == NULL)
@@ -3439,7 +3556,8 @@ int cmd_script(int argc, const char **argv)
3439 script.session = session; 3556 script.session = session;
3440 script__setup_sample_type(&script); 3557 script__setup_sample_type(&script);
3441 3558
3442 if (output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) 3559 if ((output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) ||
3560 symbol_conf.graph_function)
3443 itrace_synth_opts.thread_stack = true; 3561 itrace_synth_opts.thread_stack = true;
3444 3562
3445 session->itrace_synth_opts = &itrace_synth_opts; 3563 session->itrace_synth_opts = &itrace_synth_opts;
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index b86aba1c8028..d1028d7755bb 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -409,6 +409,28 @@ static struct perf_evsel *perf_evsel__reset_weak_group(struct perf_evsel *evsel)
409 return leader; 409 return leader;
410} 410}
411 411
412static bool is_target_alive(struct target *_target,
413 struct thread_map *threads)
414{
415 struct stat st;
416 int i;
417
418 if (!target__has_task(_target))
419 return true;
420
421 for (i = 0; i < threads->nr; i++) {
422 char path[PATH_MAX];
423
424 scnprintf(path, PATH_MAX, "%s/%d", procfs__mountpoint(),
425 threads->map[i].pid);
426
427 if (!stat(path, &st))
428 return true;
429 }
430
431 return false;
432}
433
412static int __run_perf_stat(int argc, const char **argv, int run_idx) 434static int __run_perf_stat(int argc, const char **argv, int run_idx)
413{ 435{
414 int interval = stat_config.interval; 436 int interval = stat_config.interval;
@@ -579,6 +601,8 @@ try_again:
579 enable_counters(); 601 enable_counters();
580 while (!done) { 602 while (!done) {
581 nanosleep(&ts, NULL); 603 nanosleep(&ts, NULL);
604 if (!is_target_alive(&target, evsel_list->threads))
605 break;
582 if (timeout) 606 if (timeout)
583 break; 607 break;
584 if (interval) { 608 if (interval) {
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index d21d8751e749..b2838de13de0 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1134,11 +1134,6 @@ static int __cmd_top(struct perf_top *top)
1134 if (!target__none(&opts->target)) 1134 if (!target__none(&opts->target))
1135 perf_evlist__enable(top->evlist); 1135 perf_evlist__enable(top->evlist);
1136 1136
1137 /* Wait for a minimal set of events before starting the snapshot */
1138 perf_evlist__poll(top->evlist, 100);
1139
1140 perf_top__mmap_read(top);
1141
1142 ret = -1; 1137 ret = -1;
1143 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : 1138 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
1144 display_thread), top)) { 1139 display_thread), top)) {
@@ -1156,6 +1151,11 @@ static int __cmd_top(struct perf_top *top)
1156 } 1151 }
1157 } 1152 }
1158 1153
1154 /* Wait for a minimal set of events before starting the snapshot */
1155 perf_evlist__poll(top->evlist, 100);
1156
1157 perf_top__mmap_read(top);
1158
1159 while (!done) { 1159 while (!done) {
1160 u64 hits = top->samples; 1160 u64 hits = top->samples;
1161 1161
@@ -1257,7 +1257,14 @@ int cmd_top(int argc, const char **argv)
1257 .uses_mmap = true, 1257 .uses_mmap = true,
1258 }, 1258 },
1259 .proc_map_timeout = 500, 1259 .proc_map_timeout = 500,
1260 .overwrite = 1, 1260 /*
1261 * FIXME: This will lose PERF_RECORD_MMAP and other metadata
1262 * when we pause, fix that and reenable. Probably using a
1263 * separate evlist with a dummy event, i.e. a non-overwrite
1264 * ring buffer just for metadata events, while PERF_RECORD_SAMPLE
1265 * stays in overwrite mode. -acme
1266 * */
1267 .overwrite = 0,
1261 }, 1268 },
1262 .max_stack = sysctl__max_stack(), 1269 .max_stack = sysctl__max_stack(),
1263 .annotation_opts = annotation__default_options, 1270 .annotation_opts = annotation__default_options,
@@ -1372,6 +1379,8 @@ int cmd_top(int argc, const char **argv)
1372 "Show raw trace event output (do not use print fmt or plugins)"), 1379 "Show raw trace event output (do not use print fmt or plugins)"),
1373 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy, 1380 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
1374 "Show entries in a hierarchy"), 1381 "Show entries in a hierarchy"),
1382 OPT_BOOLEAN(0, "overwrite", &top.record_opts.overwrite,
1383 "Use a backward ring buffer, default: no"),
1375 OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"), 1384 OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"),
1376 OPT_UINTEGER(0, "num-thread-synthesize", &top.nr_threads_synthesize, 1385 OPT_UINTEGER(0, "num-thread-synthesize", &top.nr_threads_synthesize,
1377 "number of thread to run event synthesize"), 1386 "number of thread to run event synthesize"),
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 90289f31dd87..dc8a6c4986ce 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -89,6 +89,8 @@ struct trace {
89 u64 base_time; 89 u64 base_time;
90 FILE *output; 90 FILE *output;
91 unsigned long nr_events; 91 unsigned long nr_events;
92 unsigned long nr_events_printed;
93 unsigned long max_events;
92 struct strlist *ev_qualifier; 94 struct strlist *ev_qualifier;
93 struct { 95 struct {
94 size_t nr; 96 size_t nr;
@@ -612,6 +614,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
612 614
613struct syscall_arg_fmt { 615struct syscall_arg_fmt {
614 size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg); 616 size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
617 unsigned long (*mask_val)(struct syscall_arg *arg, unsigned long val);
615 void *parm; 618 void *parm;
616 const char *name; 619 const char *name;
617 bool show_zero; 620 bool show_zero;
@@ -723,6 +726,10 @@ static struct syscall_fmt {
723 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, 726 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
724 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, 727 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
725 [3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, }, 728 [3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, },
729 { .name = "mount",
730 .arg = { [0] = { .scnprintf = SCA_FILENAME, /* dev_name */ },
731 [3] = { .scnprintf = SCA_MOUNT_FLAGS, /* flags */
732 .mask_val = SCAMV_MOUNT_FLAGS, /* flags */ }, }, },
726 { .name = "mprotect", 733 { .name = "mprotect",
727 .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ }, 734 .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
728 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, }, 735 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, },
@@ -832,7 +839,8 @@ static struct syscall_fmt {
832 .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, 839 .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
833 { .name = "tkill", 840 { .name = "tkill",
834 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, 841 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
835 { .name = "umount2", .alias = "umount", }, 842 { .name = "umount2", .alias = "umount",
843 .arg = { [0] = { .scnprintf = SCA_FILENAME, /* name */ }, }, },
836 { .name = "uname", .alias = "newuname", }, 844 { .name = "uname", .alias = "newuname", },
837 { .name = "unlinkat", 845 { .name = "unlinkat",
838 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, }, 846 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
@@ -856,6 +864,18 @@ static struct syscall_fmt *syscall_fmt__find(const char *name)
856 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp); 864 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
857} 865}
858 866
867static struct syscall_fmt *syscall_fmt__find_by_alias(const char *alias)
868{
869 int i, nmemb = ARRAY_SIZE(syscall_fmts);
870
871 for (i = 0; i < nmemb; ++i) {
872 if (syscall_fmts[i].alias && strcmp(syscall_fmts[i].alias, alias) == 0)
873 return &syscall_fmts[i];
874 }
875
876 return NULL;
877}
878
859/* 879/*
860 * is_exit: is this "exit" or "exit_group"? 880 * is_exit: is this "exit" or "exit_group"?
861 * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter. 881 * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter.
@@ -1485,6 +1505,19 @@ static size_t syscall__scnprintf_name(struct syscall *sc, char *bf, size_t size,
1485 return scnprintf(bf, size, "arg%d: ", arg->idx); 1505 return scnprintf(bf, size, "arg%d: ", arg->idx);
1486} 1506}
1487 1507
1508/*
1509 * Check if the value is in fact zero, i.e. mask whatever needs masking, such
1510 * as mount 'flags' argument that needs ignoring some magic flag, see comment
1511 * in tools/perf/trace/beauty/mount_flags.c
1512 */
1513static unsigned long syscall__mask_val(struct syscall *sc, struct syscall_arg *arg, unsigned long val)
1514{
1515 if (sc->arg_fmt && sc->arg_fmt[arg->idx].mask_val)
1516 return sc->arg_fmt[arg->idx].mask_val(arg, val);
1517
1518 return val;
1519}
1520
1488static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size, 1521static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size,
1489 struct syscall_arg *arg, unsigned long val) 1522 struct syscall_arg *arg, unsigned long val)
1490{ 1523{
@@ -1533,6 +1566,11 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1533 continue; 1566 continue;
1534 1567
1535 val = syscall_arg__val(&arg, arg.idx); 1568 val = syscall_arg__val(&arg, arg.idx);
1569 /*
1570 * Some syscall args need some mask, most don't and
1571 * return val untouched.
1572 */
1573 val = syscall__mask_val(sc, &arg, val);
1536 1574
1537 /* 1575 /*
1538 * Suppress this argument if its value is zero and 1576 * Suppress this argument if its value is zero and
@@ -1664,6 +1702,8 @@ static int trace__printf_interrupted_entry(struct trace *trace)
1664 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str); 1702 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1665 ttrace->entry_pending = false; 1703 ttrace->entry_pending = false;
1666 1704
1705 ++trace->nr_events_printed;
1706
1667 return printed; 1707 return printed;
1668} 1708}
1669 1709
@@ -1810,12 +1850,14 @@ static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evse
1810 int max_stack = evsel->attr.sample_max_stack ? 1850 int max_stack = evsel->attr.sample_max_stack ?
1811 evsel->attr.sample_max_stack : 1851 evsel->attr.sample_max_stack :
1812 trace->max_stack; 1852 trace->max_stack;
1853 int err;
1813 1854
1814 if (machine__resolve(trace->host, &al, sample) < 0 || 1855 if (machine__resolve(trace->host, &al, sample) < 0)
1815 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, max_stack))
1816 return -1; 1856 return -1;
1817 1857
1818 return 0; 1858 err = thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, max_stack);
1859 addr_location__put(&al);
1860 return err;
1819} 1861}
1820 1862
1821static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample) 1863static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
@@ -1940,6 +1982,13 @@ errno_print: {
1940 1982
1941 fputc('\n', trace->output); 1983 fputc('\n', trace->output);
1942 1984
1985 /*
1986 * We only consider an 'event' for the sake of --max-events a non-filtered
1987 * sys_enter + sys_exit and other tracepoint events.
1988 */
1989 if (++trace->nr_events_printed == trace->max_events && trace->max_events != ULONG_MAX)
1990 interrupted = true;
1991
1943 if (callchain_ret > 0) 1992 if (callchain_ret > 0)
1944 trace__fprintf_callchain(trace, sample); 1993 trace__fprintf_callchain(trace, sample);
1945 else if (callchain_ret < 0) 1994 else if (callchain_ret < 0)
@@ -2072,14 +2121,25 @@ static void bpf_output__fprintf(struct trace *trace,
2072{ 2121{
2073 binary__fprintf(sample->raw_data, sample->raw_size, 8, 2122 binary__fprintf(sample->raw_data, sample->raw_size, 8,
2074 bpf_output__printer, NULL, trace->output); 2123 bpf_output__printer, NULL, trace->output);
2124 ++trace->nr_events_printed;
2075} 2125}
2076 2126
2077static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, 2127static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2078 union perf_event *event __maybe_unused, 2128 union perf_event *event __maybe_unused,
2079 struct perf_sample *sample) 2129 struct perf_sample *sample)
2080{ 2130{
2081 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 2131 struct thread *thread;
2082 int callchain_ret = 0; 2132 int callchain_ret = 0;
2133 /*
2134 * Check if we called perf_evsel__disable(evsel) due to, for instance,
2135 * this event's max_events having been hit and this is an entry coming
2136 * from the ring buffer that we should discard, since the max events
2137 * have already been considered/printed.
2138 */
2139 if (evsel->disabled)
2140 return 0;
2141
2142 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
2083 2143
2084 if (sample->callchain) { 2144 if (sample->callchain) {
2085 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor); 2145 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
@@ -2127,6 +2187,12 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2127 event_format__fprintf(evsel->tp_format, sample->cpu, 2187 event_format__fprintf(evsel->tp_format, sample->cpu,
2128 sample->raw_data, sample->raw_size, 2188 sample->raw_data, sample->raw_size,
2129 trace->output); 2189 trace->output);
2190 ++trace->nr_events_printed;
2191
2192 if (evsel->max_events != ULONG_MAX && ++evsel->nr_events_printed == evsel->max_events) {
2193 perf_evsel__disable(evsel);
2194 perf_evsel__close(evsel);
2195 }
2130 } 2196 }
2131 } 2197 }
2132 2198
@@ -2137,8 +2203,8 @@ newline:
2137 trace__fprintf_callchain(trace, sample); 2203 trace__fprintf_callchain(trace, sample);
2138 else if (callchain_ret < 0) 2204 else if (callchain_ret < 0)
2139 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); 2205 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2140 thread__put(thread);
2141out: 2206out:
2207 thread__put(thread);
2142 return 0; 2208 return 0;
2143} 2209}
2144 2210
@@ -2225,6 +2291,8 @@ static int trace__pgfault(struct trace *trace,
2225 trace__fprintf_callchain(trace, sample); 2291 trace__fprintf_callchain(trace, sample);
2226 else if (callchain_ret < 0) 2292 else if (callchain_ret < 0)
2227 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); 2293 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2294
2295 ++trace->nr_events_printed;
2228out: 2296out:
2229 err = 0; 2297 err = 0;
2230out_put: 2298out_put:
@@ -2402,6 +2470,9 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
2402 tracepoint_handler handler = evsel->handler; 2470 tracepoint_handler handler = evsel->handler;
2403 handler(trace, evsel, event, sample); 2471 handler(trace, evsel, event, sample);
2404 } 2472 }
2473
2474 if (trace->nr_events_printed >= trace->max_events && trace->max_events != ULONG_MAX)
2475 interrupted = true;
2405} 2476}
2406 2477
2407static int trace__add_syscall_newtp(struct trace *trace) 2478static int trace__add_syscall_newtp(struct trace *trace)
@@ -2706,7 +2777,7 @@ next_event:
2706 int timeout = done ? 100 : -1; 2777 int timeout = done ? 100 : -1;
2707 2778
2708 if (!draining && perf_evlist__poll(evlist, timeout) > 0) { 2779 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2709 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0) 2780 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP | POLLNVAL) == 0)
2710 draining = true; 2781 draining = true;
2711 2782
2712 goto again; 2783 goto again;
@@ -3138,6 +3209,7 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
3138 int len = strlen(str) + 1, err = -1, list, idx; 3209 int len = strlen(str) + 1, err = -1, list, idx;
3139 char *strace_groups_dir = system_path(STRACE_GROUPS_DIR); 3210 char *strace_groups_dir = system_path(STRACE_GROUPS_DIR);
3140 char group_name[PATH_MAX]; 3211 char group_name[PATH_MAX];
3212 struct syscall_fmt *fmt;
3141 3213
3142 if (strace_groups_dir == NULL) 3214 if (strace_groups_dir == NULL)
3143 return -1; 3215 return -1;
@@ -3155,12 +3227,19 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
3155 if (syscalltbl__id(trace->sctbl, s) >= 0 || 3227 if (syscalltbl__id(trace->sctbl, s) >= 0 ||
3156 syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) { 3228 syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) {
3157 list = 1; 3229 list = 1;
3230 goto do_concat;
3231 }
3232
3233 fmt = syscall_fmt__find_by_alias(s);
3234 if (fmt != NULL) {
3235 list = 1;
3236 s = fmt->name;
3158 } else { 3237 } else {
3159 path__join(group_name, sizeof(group_name), strace_groups_dir, s); 3238 path__join(group_name, sizeof(group_name), strace_groups_dir, s);
3160 if (access(group_name, R_OK) == 0) 3239 if (access(group_name, R_OK) == 0)
3161 list = 1; 3240 list = 1;
3162 } 3241 }
3163 3242do_concat:
3164 if (lists[list]) { 3243 if (lists[list]) {
3165 sprintf(lists[list] + strlen(lists[list]), ",%s", s); 3244 sprintf(lists[list] + strlen(lists[list]), ",%s", s);
3166 } else { 3245 } else {
@@ -3249,6 +3328,7 @@ int cmd_trace(int argc, const char **argv)
3249 .trace_syscalls = false, 3328 .trace_syscalls = false,
3250 .kernel_syscallchains = false, 3329 .kernel_syscallchains = false,
3251 .max_stack = UINT_MAX, 3330 .max_stack = UINT_MAX,
3331 .max_events = ULONG_MAX,
3252 }; 3332 };
3253 const char *output_name = NULL; 3333 const char *output_name = NULL;
3254 const struct option trace_options[] = { 3334 const struct option trace_options[] = {
@@ -3301,6 +3381,8 @@ int cmd_trace(int argc, const char **argv)
3301 &record_parse_callchain_opt), 3381 &record_parse_callchain_opt),
3302 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains, 3382 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
3303 "Show the kernel callchains on the syscall exit path"), 3383 "Show the kernel callchains on the syscall exit path"),
3384 OPT_ULONG(0, "max-events", &trace.max_events,
3385 "Set the maximum number of events to print, exit after that is reached. "),
3304 OPT_UINTEGER(0, "min-stack", &trace.min_stack, 3386 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
3305 "Set the minimum stack depth when parsing the callchain, " 3387 "Set the minimum stack depth when parsing the callchain, "
3306 "anything below the specified depth will be ignored."), 3388 "anything below the specified depth will be ignored."),
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index c72cc73a6b09..9531f7bd7d9b 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -5,6 +5,7 @@ HEADERS='
5include/uapi/drm/drm.h 5include/uapi/drm/drm.h
6include/uapi/drm/i915_drm.h 6include/uapi/drm/i915_drm.h
7include/uapi/linux/fcntl.h 7include/uapi/linux/fcntl.h
8include/uapi/linux/fs.h
8include/uapi/linux/kcmp.h 9include/uapi/linux/kcmp.h
9include/uapi/linux/kvm.h 10include/uapi/linux/kvm.h
10include/uapi/linux/in.h 11include/uapi/linux/in.h
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 21bf7f5a3cf5..0ed4a34c74c4 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -81,6 +81,7 @@ struct record_opts {
81 unsigned initial_delay; 81 unsigned initial_delay;
82 bool use_clockid; 82 bool use_clockid;
83 clockid_t clockid; 83 clockid_t clockid;
84 u64 clockid_res_ns;
84 unsigned int proc_map_timeout; 85 unsigned int proc_map_timeout;
85}; 86};
86 87
diff --git a/tools/perf/scripts/python/call-graph-from-sql.py b/tools/perf/scripts/python/call-graph-from-sql.py
deleted file mode 100644
index b494a67a1c67..000000000000
--- a/tools/perf/scripts/python/call-graph-from-sql.py
+++ /dev/null
@@ -1,339 +0,0 @@
1#!/usr/bin/python2
2# call-graph-from-sql.py: create call-graph from sql database
3# Copyright (c) 2014-2017, Intel Corporation.
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms and conditions of the GNU General Public License,
7# version 2, as published by the Free Software Foundation.
8#
9# This program is distributed in the hope it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12# more details.
13
14# To use this script you will need to have exported data using either the
15# export-to-sqlite.py or the export-to-postgresql.py script. Refer to those
16# scripts for details.
17#
18# Following on from the example in the export scripts, a
19# call-graph can be displayed for the pt_example database like this:
20#
21# python tools/perf/scripts/python/call-graph-from-sql.py pt_example
22#
23# Note that for PostgreSQL, this script supports connecting to remote databases
24# by setting hostname, port, username, password, and dbname e.g.
25#
26# python tools/perf/scripts/python/call-graph-from-sql.py "hostname=myhost username=myuser password=mypassword dbname=pt_example"
27#
28# The result is a GUI window with a tree representing a context-sensitive
29# call-graph. Expanding a couple of levels of the tree and adjusting column
30# widths to suit will display something like:
31#
32# Call Graph: pt_example
33# Call Path Object Count Time(ns) Time(%) Branch Count Branch Count(%)
34# v- ls
35# v- 2638:2638
36# v- _start ld-2.19.so 1 10074071 100.0 211135 100.0
37# |- unknown unknown 1 13198 0.1 1 0.0
38# >- _dl_start ld-2.19.so 1 1400980 13.9 19637 9.3
39# >- _d_linit_internal ld-2.19.so 1 448152 4.4 11094 5.3
40# v-__libc_start_main@plt ls 1 8211741 81.5 180397 85.4
41# >- _dl_fixup ld-2.19.so 1 7607 0.1 108 0.1
42# >- __cxa_atexit libc-2.19.so 1 11737 0.1 10 0.0
43# >- __libc_csu_init ls 1 10354 0.1 10 0.0
44# |- _setjmp libc-2.19.so 1 0 0.0 4 0.0
45# v- main ls 1 8182043 99.6 180254 99.9
46#
47# Points to note:
48# The top level is a command name (comm)
49# The next level is a thread (pid:tid)
50# Subsequent levels are functions
51# 'Count' is the number of calls
52# 'Time' is the elapsed time until the function returns
53# Percentages are relative to the level above
54# 'Branch Count' is the total number of branches for that function and all
55# functions that it calls
56
57import sys
58from PySide.QtCore import *
59from PySide.QtGui import *
60from PySide.QtSql import *
61from decimal import *
62
63class TreeItem():
64
65 def __init__(self, db, row, parent_item):
66 self.db = db
67 self.row = row
68 self.parent_item = parent_item
69 self.query_done = False;
70 self.child_count = 0
71 self.child_items = []
72 self.data = ["", "", "", "", "", "", ""]
73 self.comm_id = 0
74 self.thread_id = 0
75 self.call_path_id = 1
76 self.branch_count = 0
77 self.time = 0
78 if not parent_item:
79 self.setUpRoot()
80
81 def setUpRoot(self):
82 self.query_done = True
83 query = QSqlQuery(self.db)
84 ret = query.exec_('SELECT id, comm FROM comms')
85 if not ret:
86 raise Exception("Query failed: " + query.lastError().text())
87 while query.next():
88 if not query.value(0):
89 continue
90 child_item = TreeItem(self.db, self.child_count, self)
91 self.child_items.append(child_item)
92 self.child_count += 1
93 child_item.setUpLevel1(query.value(0), query.value(1))
94
95 def setUpLevel1(self, comm_id, comm):
96 self.query_done = True;
97 self.comm_id = comm_id
98 self.data[0] = comm
99 self.child_items = []
100 self.child_count = 0
101 query = QSqlQuery(self.db)
102 ret = query.exec_('SELECT thread_id, ( SELECT pid FROM threads WHERE id = thread_id ), ( SELECT tid FROM threads WHERE id = thread_id ) FROM comm_threads WHERE comm_id = ' + str(comm_id))
103 if not ret:
104 raise Exception("Query failed: " + query.lastError().text())
105 while query.next():
106 child_item = TreeItem(self.db, self.child_count, self)
107 self.child_items.append(child_item)
108 self.child_count += 1
109 child_item.setUpLevel2(comm_id, query.value(0), query.value(1), query.value(2))
110
111 def setUpLevel2(self, comm_id, thread_id, pid, tid):
112 self.comm_id = comm_id
113 self.thread_id = thread_id
114 self.data[0] = str(pid) + ":" + str(tid)
115
116 def getChildItem(self, row):
117 return self.child_items[row]
118
119 def getParentItem(self):
120 return self.parent_item
121
122 def getRow(self):
123 return self.row
124
125 def timePercent(self, b):
126 if not self.time:
127 return "0.0"
128 x = (b * Decimal(100)) / self.time
129 return str(x.quantize(Decimal('.1'), rounding=ROUND_HALF_UP))
130
131 def branchPercent(self, b):
132 if not self.branch_count:
133 return "0.0"
134 x = (b * Decimal(100)) / self.branch_count
135 return str(x.quantize(Decimal('.1'), rounding=ROUND_HALF_UP))
136
137 def addChild(self, call_path_id, name, dso, count, time, branch_count):
138 child_item = TreeItem(self.db, self.child_count, self)
139 child_item.comm_id = self.comm_id
140 child_item.thread_id = self.thread_id
141 child_item.call_path_id = call_path_id
142 child_item.branch_count = branch_count
143 child_item.time = time
144 child_item.data[0] = name
145 if dso == "[kernel.kallsyms]":
146 dso = "[kernel]"
147 child_item.data[1] = dso
148 child_item.data[2] = str(count)
149 child_item.data[3] = str(time)
150 child_item.data[4] = self.timePercent(time)
151 child_item.data[5] = str(branch_count)
152 child_item.data[6] = self.branchPercent(branch_count)
153 self.child_items.append(child_item)
154 self.child_count += 1
155
156 def selectCalls(self):
157 self.query_done = True;
158 query = QSqlQuery(self.db)
159 ret = query.exec_('SELECT id, call_path_id, branch_count, call_time, return_time, '
160 '( SELECT name FROM symbols WHERE id = ( SELECT symbol_id FROM call_paths WHERE id = call_path_id ) ), '
161 '( SELECT short_name FROM dsos WHERE id = ( SELECT dso_id FROM symbols WHERE id = ( SELECT symbol_id FROM call_paths WHERE id = call_path_id ) ) ), '
162 '( SELECT ip FROM call_paths where id = call_path_id ) '
163 'FROM calls WHERE parent_call_path_id = ' + str(self.call_path_id) + ' AND comm_id = ' + str(self.comm_id) + ' AND thread_id = ' + str(self.thread_id) +
164 ' ORDER BY call_path_id')
165 if not ret:
166 raise Exception("Query failed: " + query.lastError().text())
167 last_call_path_id = 0
168 name = ""
169 dso = ""
170 count = 0
171 branch_count = 0
172 total_branch_count = 0
173 time = 0
174 total_time = 0
175 while query.next():
176 if query.value(1) == last_call_path_id:
177 count += 1
178 branch_count += query.value(2)
179 time += query.value(4) - query.value(3)
180 else:
181 if count:
182 self.addChild(last_call_path_id, name, dso, count, time, branch_count)
183 last_call_path_id = query.value(1)
184 name = query.value(5)
185 dso = query.value(6)
186 count = 1
187 total_branch_count += branch_count
188 total_time += time
189 branch_count = query.value(2)
190 time = query.value(4) - query.value(3)
191 if count:
192 self.addChild(last_call_path_id, name, dso, count, time, branch_count)
193 total_branch_count += branch_count
194 total_time += time
195 # Top level does not have time or branch count, so fix that here
196 if total_branch_count > self.branch_count:
197 self.branch_count = total_branch_count
198 if self.branch_count:
199 for child_item in self.child_items:
200 child_item.data[6] = self.branchPercent(child_item.branch_count)
201 if total_time > self.time:
202 self.time = total_time
203 if self.time:
204 for child_item in self.child_items:
205 child_item.data[4] = self.timePercent(child_item.time)
206
207 def childCount(self):
208 if not self.query_done:
209 self.selectCalls()
210 return self.child_count
211
212 def columnCount(self):
213 return 7
214
215 def columnHeader(self, column):
216 headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]
217 return headers[column]
218
219 def getData(self, column):
220 return self.data[column]
221
222class TreeModel(QAbstractItemModel):
223
224 def __init__(self, db, parent=None):
225 super(TreeModel, self).__init__(parent)
226 self.db = db
227 self.root = TreeItem(db, 0, None)
228
229 def columnCount(self, parent):
230 return self.root.columnCount()
231
232 def rowCount(self, parent):
233 if parent.isValid():
234 parent_item = parent.internalPointer()
235 else:
236 parent_item = self.root
237 return parent_item.childCount()
238
239 def headerData(self, section, orientation, role):
240 if role == Qt.TextAlignmentRole:
241 if section > 1:
242 return Qt.AlignRight
243 if role != Qt.DisplayRole:
244 return None
245 if orientation != Qt.Horizontal:
246 return None
247 return self.root.columnHeader(section)
248
249 def parent(self, child):
250 child_item = child.internalPointer()
251 if child_item is self.root:
252 return QModelIndex()
253 parent_item = child_item.getParentItem()
254 return self.createIndex(parent_item.getRow(), 0, parent_item)
255
256 def index(self, row, column, parent):
257 if parent.isValid():
258 parent_item = parent.internalPointer()
259 else:
260 parent_item = self.root
261 child_item = parent_item.getChildItem(row)
262 return self.createIndex(row, column, child_item)
263
264 def data(self, index, role):
265 if role == Qt.TextAlignmentRole:
266 if index.column() > 1:
267 return Qt.AlignRight
268 if role != Qt.DisplayRole:
269 return None
270 index_item = index.internalPointer()
271 return index_item.getData(index.column())
272
273class MainWindow(QMainWindow):
274
275 def __init__(self, db, dbname, parent=None):
276 super(MainWindow, self).__init__(parent)
277
278 self.setObjectName("MainWindow")
279 self.setWindowTitle("Call Graph: " + dbname)
280 self.move(100, 100)
281 self.resize(800, 600)
282 style = self.style()
283 icon = style.standardIcon(QStyle.SP_MessageBoxInformation)
284 self.setWindowIcon(icon);
285
286 self.model = TreeModel(db)
287
288 self.view = QTreeView()
289 self.view.setModel(self.model)
290
291 self.setCentralWidget(self.view)
292
293if __name__ == '__main__':
294 if (len(sys.argv) < 2):
295 print >> sys.stderr, "Usage is: call-graph-from-sql.py <database name>"
296 raise Exception("Too few arguments")
297
298 dbname = sys.argv[1]
299
300 is_sqlite3 = False
301 try:
302 f = open(dbname)
303 if f.read(15) == "SQLite format 3":
304 is_sqlite3 = True
305 f.close()
306 except:
307 pass
308
309 if is_sqlite3:
310 db = QSqlDatabase.addDatabase('QSQLITE')
311 else:
312 db = QSqlDatabase.addDatabase('QPSQL')
313 opts = dbname.split()
314 for opt in opts:
315 if '=' in opt:
316 opt = opt.split('=')
317 if opt[0] == 'hostname':
318 db.setHostName(opt[1])
319 elif opt[0] == 'port':
320 db.setPort(int(opt[1]))
321 elif opt[0] == 'username':
322 db.setUserName(opt[1])
323 elif opt[0] == 'password':
324 db.setPassword(opt[1])
325 elif opt[0] == 'dbname':
326 dbname = opt[1]
327 else:
328 dbname = opt
329
330 db.setDatabaseName(dbname)
331 if not db.open():
332 raise Exception("Failed to open database " + dbname + " error: " + db.lastError().text())
333
334 app = QApplication(sys.argv)
335 window = MainWindow(db, dbname)
336 window.show()
337 err = app.exec_()
338 db.close()
339 sys.exit(err)
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index e46f51b17513..0564dd7377f2 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -59,7 +59,7 @@ import datetime
59# pt_example=# \q 59# pt_example=# \q
60# 60#
61# An example of using the database is provided by the script 61# An example of using the database is provided by the script
62# call-graph-from-sql.py. Refer to that script for details. 62# exported-sql-viewer.py. Refer to that script for details.
63# 63#
64# Tables: 64# Tables:
65# 65#
diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py
index e4bb82c8aba9..245caf2643ed 100644
--- a/tools/perf/scripts/python/export-to-sqlite.py
+++ b/tools/perf/scripts/python/export-to-sqlite.py
@@ -40,7 +40,7 @@ import datetime
40# sqlite> .quit 40# sqlite> .quit
41# 41#
42# An example of using the database is provided by the script 42# An example of using the database is provided by the script
43# call-graph-from-sql.py. Refer to that script for details. 43# exported-sql-viewer.py. Refer to that script for details.
44# 44#
45# The database structure is practically the same as created by the script 45# The database structure is practically the same as created by the script
46# export-to-postgresql.py. Refer to that script for details. A notable 46# export-to-postgresql.py. Refer to that script for details. A notable
diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py
new file mode 100755
index 000000000000..24cb0bd56afa
--- /dev/null
+++ b/tools/perf/scripts/python/exported-sql-viewer.py
@@ -0,0 +1,2128 @@
1#!/usr/bin/python2
2# SPDX-License-Identifier: GPL-2.0
3# exported-sql-viewer.py: view data from sql database
4# Copyright (c) 2014-2018, Intel Corporation.
5
6# To use this script you will need to have exported data using either the
7# export-to-sqlite.py or the export-to-postgresql.py script. Refer to those
8# scripts for details.
9#
10# Following on from the example in the export scripts, a
11# call-graph can be displayed for the pt_example database like this:
12#
13# python tools/perf/scripts/python/exported-sql-viewer.py pt_example
14#
15# Note that for PostgreSQL, this script supports connecting to remote databases
16# by setting hostname, port, username, password, and dbname e.g.
17#
18# python tools/perf/scripts/python/exported-sql-viewer.py "hostname=myhost username=myuser password=mypassword dbname=pt_example"
19#
20# The result is a GUI window with a tree representing a context-sensitive
21# call-graph. Expanding a couple of levels of the tree and adjusting column
22# widths to suit will display something like:
23#
24# Call Graph: pt_example
25# Call Path Object Count Time(ns) Time(%) Branch Count Branch Count(%)
26# v- ls
27# v- 2638:2638
28# v- _start ld-2.19.so 1 10074071 100.0 211135 100.0
29# |- unknown unknown 1 13198 0.1 1 0.0
30# >- _dl_start ld-2.19.so 1 1400980 13.9 19637 9.3
31# >- _d_linit_internal ld-2.19.so 1 448152 4.4 11094 5.3
32# v-__libc_start_main@plt ls 1 8211741 81.5 180397 85.4
33# >- _dl_fixup ld-2.19.so 1 7607 0.1 108 0.1
34# >- __cxa_atexit libc-2.19.so 1 11737 0.1 10 0.0
35# >- __libc_csu_init ls 1 10354 0.1 10 0.0
36# |- _setjmp libc-2.19.so 1 0 0.0 4 0.0
37# v- main ls 1 8182043 99.6 180254 99.9
38#
39# Points to note:
40# The top level is a command name (comm)
41# The next level is a thread (pid:tid)
42# Subsequent levels are functions
43# 'Count' is the number of calls
44# 'Time' is the elapsed time until the function returns
45# Percentages are relative to the level above
46# 'Branch Count' is the total number of branches for that function and all
47# functions that it calls
48
49# There is also a "All branches" report, which displays branches and
50# possibly disassembly. However, presently, the only supported disassembler is
51# Intel XED, and additionally the object code must be present in perf build ID
52# cache. To use Intel XED, libxed.so must be present. To build and install
53# libxed.so:
54# git clone https://github.com/intelxed/mbuild.git mbuild
55# git clone https://github.com/intelxed/xed
56# cd xed
57# ./mfile.py --share
58# sudo ./mfile.py --prefix=/usr/local install
59# sudo ldconfig
60#
61# Example report:
62#
63# Time CPU Command PID TID Branch Type In Tx Branch
64# 8107675239590 2 ls 22011 22011 return from interrupt No ffffffff86a00a67 native_irq_return_iret ([kernel]) -> 7fab593ea260 _start (ld-2.19.so)
65# 7fab593ea260 48 89 e7 mov %rsp, %rdi
66# 8107675239899 2 ls 22011 22011 hardware interrupt No 7fab593ea260 _start (ld-2.19.so) -> ffffffff86a012e0 page_fault ([kernel])
67# 8107675241900 2 ls 22011 22011 return from interrupt No ffffffff86a00a67 native_irq_return_iret ([kernel]) -> 7fab593ea260 _start (ld-2.19.so)
68# 7fab593ea260 48 89 e7 mov %rsp, %rdi
69# 7fab593ea263 e8 c8 06 00 00 callq 0x7fab593ea930
70# 8107675241900 2 ls 22011 22011 call No 7fab593ea263 _start+0x3 (ld-2.19.so) -> 7fab593ea930 _dl_start (ld-2.19.so)
71# 7fab593ea930 55 pushq %rbp
72# 7fab593ea931 48 89 e5 mov %rsp, %rbp
73# 7fab593ea934 41 57 pushq %r15
74# 7fab593ea936 41 56 pushq %r14
75# 7fab593ea938 41 55 pushq %r13
76# 7fab593ea93a 41 54 pushq %r12
77# 7fab593ea93c 53 pushq %rbx
78# 7fab593ea93d 48 89 fb mov %rdi, %rbx
79# 7fab593ea940 48 83 ec 68 sub $0x68, %rsp
80# 7fab593ea944 0f 31 rdtsc
81# 7fab593ea946 48 c1 e2 20 shl $0x20, %rdx
82# 7fab593ea94a 89 c0 mov %eax, %eax
83# 7fab593ea94c 48 09 c2 or %rax, %rdx
84# 7fab593ea94f 48 8b 05 1a 15 22 00 movq 0x22151a(%rip), %rax
85# 8107675242232 2 ls 22011 22011 hardware interrupt No 7fab593ea94f _dl_start+0x1f (ld-2.19.so) -> ffffffff86a012e0 page_fault ([kernel])
86# 8107675242900 2 ls 22011 22011 return from interrupt No ffffffff86a00a67 native_irq_return_iret ([kernel]) -> 7fab593ea94f _dl_start+0x1f (ld-2.19.so)
87# 7fab593ea94f 48 8b 05 1a 15 22 00 movq 0x22151a(%rip), %rax
88# 7fab593ea956 48 89 15 3b 13 22 00 movq %rdx, 0x22133b(%rip)
89# 8107675243232 2 ls 22011 22011 hardware interrupt No 7fab593ea956 _dl_start+0x26 (ld-2.19.so) -> ffffffff86a012e0 page_fault ([kernel])
90
91import sys
92import weakref
93import threading
94import string
95import cPickle
96import re
97import os
98from PySide.QtCore import *
99from PySide.QtGui import *
100from PySide.QtSql import *
101from decimal import *
102from ctypes import *
103from multiprocessing import Process, Array, Value, Event
104
105# Data formatting helpers
106
107def tohex(ip):
108 if ip < 0:
109 ip += 1 << 64
110 return "%x" % ip
111
112def offstr(offset):
113 if offset:
114 return "+0x%x" % offset
115 return ""
116
117def dsoname(name):
118 if name == "[kernel.kallsyms]":
119 return "[kernel]"
120 return name
121
122# Percent to one decimal place
123
124def PercentToOneDP(n, d):
125 if not d:
126 return "0.0"
127 x = (n * Decimal(100)) / d
128 return str(x.quantize(Decimal(".1"), rounding=ROUND_HALF_UP))
129
130# Helper for queries that must not fail
131
132def QueryExec(query, stmt):
133 ret = query.exec_(stmt)
134 if not ret:
135 raise Exception("Query failed: " + query.lastError().text())
136
137# Background thread
138
139class Thread(QThread):
140
141 done = Signal(object)
142
143 def __init__(self, task, param=None, parent=None):
144 super(Thread, self).__init__(parent)
145 self.task = task
146 self.param = param
147
148 def run(self):
149 while True:
150 if self.param is None:
151 done, result = self.task()
152 else:
153 done, result = self.task(self.param)
154 self.done.emit(result)
155 if done:
156 break
157
158# Tree data model
159
160class TreeModel(QAbstractItemModel):
161
162 def __init__(self, root, parent=None):
163 super(TreeModel, self).__init__(parent)
164 self.root = root
165 self.last_row_read = 0
166
167 def Item(self, parent):
168 if parent.isValid():
169 return parent.internalPointer()
170 else:
171 return self.root
172
173 def rowCount(self, parent):
174 result = self.Item(parent).childCount()
175 if result < 0:
176 result = 0
177 self.dataChanged.emit(parent, parent)
178 return result
179
180 def hasChildren(self, parent):
181 return self.Item(parent).hasChildren()
182
183 def headerData(self, section, orientation, role):
184 if role == Qt.TextAlignmentRole:
185 return self.columnAlignment(section)
186 if role != Qt.DisplayRole:
187 return None
188 if orientation != Qt.Horizontal:
189 return None
190 return self.columnHeader(section)
191
192 def parent(self, child):
193 child_item = child.internalPointer()
194 if child_item is self.root:
195 return QModelIndex()
196 parent_item = child_item.getParentItem()
197 return self.createIndex(parent_item.getRow(), 0, parent_item)
198
199 def index(self, row, column, parent):
200 child_item = self.Item(parent).getChildItem(row)
201 return self.createIndex(row, column, child_item)
202
203 def DisplayData(self, item, index):
204 return item.getData(index.column())
205
206 def FetchIfNeeded(self, row):
207 if row > self.last_row_read:
208 self.last_row_read = row
209 if row + 10 >= self.root.child_count:
210 self.fetcher.Fetch(glb_chunk_sz)
211
212 def columnAlignment(self, column):
213 return Qt.AlignLeft
214
215 def columnFont(self, column):
216 return None
217
218 def data(self, index, role):
219 if role == Qt.TextAlignmentRole:
220 return self.columnAlignment(index.column())
221 if role == Qt.FontRole:
222 return self.columnFont(index.column())
223 if role != Qt.DisplayRole:
224 return None
225 item = index.internalPointer()
226 return self.DisplayData(item, index)
227
228# Table data model
229
230class TableModel(QAbstractTableModel):
231
232 def __init__(self, parent=None):
233 super(TableModel, self).__init__(parent)
234 self.child_count = 0
235 self.child_items = []
236 self.last_row_read = 0
237
238 def Item(self, parent):
239 if parent.isValid():
240 return parent.internalPointer()
241 else:
242 return self
243
244 def rowCount(self, parent):
245 return self.child_count
246
247 def headerData(self, section, orientation, role):
248 if role == Qt.TextAlignmentRole:
249 return self.columnAlignment(section)
250 if role != Qt.DisplayRole:
251 return None
252 if orientation != Qt.Horizontal:
253 return None
254 return self.columnHeader(section)
255
256 def index(self, row, column, parent):
257 return self.createIndex(row, column, self.child_items[row])
258
259 def DisplayData(self, item, index):
260 return item.getData(index.column())
261
262 def FetchIfNeeded(self, row):
263 if row > self.last_row_read:
264 self.last_row_read = row
265 if row + 10 >= self.child_count:
266 self.fetcher.Fetch(glb_chunk_sz)
267
268 def columnAlignment(self, column):
269 return Qt.AlignLeft
270
271 def columnFont(self, column):
272 return None
273
274 def data(self, index, role):
275 if role == Qt.TextAlignmentRole:
276 return self.columnAlignment(index.column())
277 if role == Qt.FontRole:
278 return self.columnFont(index.column())
279 if role != Qt.DisplayRole:
280 return None
281 item = index.internalPointer()
282 return self.DisplayData(item, index)
283
284# Model cache
285
286model_cache = weakref.WeakValueDictionary()
287model_cache_lock = threading.Lock()
288
289def LookupCreateModel(model_name, create_fn):
290 model_cache_lock.acquire()
291 try:
292 model = model_cache[model_name]
293 except:
294 model = None
295 if model is None:
296 model = create_fn()
297 model_cache[model_name] = model
298 model_cache_lock.release()
299 return model
300
301# Find bar
302
303class FindBar():
304
305 def __init__(self, parent, finder, is_reg_expr=False):
306 self.finder = finder
307 self.context = []
308 self.last_value = None
309 self.last_pattern = None
310
311 label = QLabel("Find:")
312 label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
313
314 self.textbox = QComboBox()
315 self.textbox.setEditable(True)
316 self.textbox.currentIndexChanged.connect(self.ValueChanged)
317
318 self.progress = QProgressBar()
319 self.progress.setRange(0, 0)
320 self.progress.hide()
321
322 if is_reg_expr:
323 self.pattern = QCheckBox("Regular Expression")
324 else:
325 self.pattern = QCheckBox("Pattern")
326 self.pattern.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
327
328 self.next_button = QToolButton()
329 self.next_button.setIcon(parent.style().standardIcon(QStyle.SP_ArrowDown))
330 self.next_button.released.connect(lambda: self.NextPrev(1))
331
332 self.prev_button = QToolButton()
333 self.prev_button.setIcon(parent.style().standardIcon(QStyle.SP_ArrowUp))
334 self.prev_button.released.connect(lambda: self.NextPrev(-1))
335
336 self.close_button = QToolButton()
337 self.close_button.setIcon(parent.style().standardIcon(QStyle.SP_DockWidgetCloseButton))
338 self.close_button.released.connect(self.Deactivate)
339
340 self.hbox = QHBoxLayout()
341 self.hbox.setContentsMargins(0, 0, 0, 0)
342
343 self.hbox.addWidget(label)
344 self.hbox.addWidget(self.textbox)
345 self.hbox.addWidget(self.progress)
346 self.hbox.addWidget(self.pattern)
347 self.hbox.addWidget(self.next_button)
348 self.hbox.addWidget(self.prev_button)
349 self.hbox.addWidget(self.close_button)
350
351 self.bar = QWidget()
352 self.bar.setLayout(self.hbox);
353 self.bar.hide()
354
355 def Widget(self):
356 return self.bar
357
358 def Activate(self):
359 self.bar.show()
360 self.textbox.setFocus()
361
362 def Deactivate(self):
363 self.bar.hide()
364
365 def Busy(self):
366 self.textbox.setEnabled(False)
367 self.pattern.hide()
368 self.next_button.hide()
369 self.prev_button.hide()
370 self.progress.show()
371
372 def Idle(self):
373 self.textbox.setEnabled(True)
374 self.progress.hide()
375 self.pattern.show()
376 self.next_button.show()
377 self.prev_button.show()
378
379 def Find(self, direction):
380 value = self.textbox.currentText()
381 pattern = self.pattern.isChecked()
382 self.last_value = value
383 self.last_pattern = pattern
384 self.finder.Find(value, direction, pattern, self.context)
385
386 def ValueChanged(self):
387 value = self.textbox.currentText()
388 pattern = self.pattern.isChecked()
389 index = self.textbox.currentIndex()
390 data = self.textbox.itemData(index)
391 # Store the pattern in the combo box to keep it with the text value
392 if data == None:
393 self.textbox.setItemData(index, pattern)
394 else:
395 self.pattern.setChecked(data)
396 self.Find(0)
397
398 def NextPrev(self, direction):
399 value = self.textbox.currentText()
400 pattern = self.pattern.isChecked()
401 if value != self.last_value:
402 index = self.textbox.findText(value)
403 # Allow for a button press before the value has been added to the combo box
404 if index < 0:
405 index = self.textbox.count()
406 self.textbox.addItem(value, pattern)
407 self.textbox.setCurrentIndex(index)
408 return
409 else:
410 self.textbox.setItemData(index, pattern)
411 elif pattern != self.last_pattern:
412 # Keep the pattern recorded in the combo box up to date
413 index = self.textbox.currentIndex()
414 self.textbox.setItemData(index, pattern)
415 self.Find(direction)
416
417 def NotFound(self):
418 QMessageBox.information(self.bar, "Find", "'" + self.textbox.currentText() + "' not found")
419
420# Context-sensitive call graph data model item base
421
422class CallGraphLevelItemBase(object):
423
424 def __init__(self, glb, row, parent_item):
425 self.glb = glb
426 self.row = row
427 self.parent_item = parent_item
428 self.query_done = False;
429 self.child_count = 0
430 self.child_items = []
431
432 def getChildItem(self, row):
433 return self.child_items[row]
434
435 def getParentItem(self):
436 return self.parent_item
437
438 def getRow(self):
439 return self.row
440
441 def childCount(self):
442 if not self.query_done:
443 self.Select()
444 if not self.child_count:
445 return -1
446 return self.child_count
447
448 def hasChildren(self):
449 if not self.query_done:
450 return True
451 return self.child_count > 0
452
453 def getData(self, column):
454 return self.data[column]
455
456# Context-sensitive call graph data model level 2+ item base
457
458class CallGraphLevelTwoPlusItemBase(CallGraphLevelItemBase):
459
460 def __init__(self, glb, row, comm_id, thread_id, call_path_id, time, branch_count, parent_item):
461 super(CallGraphLevelTwoPlusItemBase, self).__init__(glb, row, parent_item)
462 self.comm_id = comm_id
463 self.thread_id = thread_id
464 self.call_path_id = call_path_id
465 self.branch_count = branch_count
466 self.time = time
467
468 def Select(self):
469 self.query_done = True;
470 query = QSqlQuery(self.glb.db)
471 QueryExec(query, "SELECT call_path_id, name, short_name, COUNT(calls.id), SUM(return_time - call_time), SUM(branch_count)"
472 " FROM calls"
473 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
474 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
475 " INNER JOIN dsos ON symbols.dso_id = dsos.id"
476 " WHERE parent_call_path_id = " + str(self.call_path_id) +
477 " AND comm_id = " + str(self.comm_id) +
478 " AND thread_id = " + str(self.thread_id) +
479 " GROUP BY call_path_id, name, short_name"
480 " ORDER BY call_path_id")
481 while query.next():
482 child_item = CallGraphLevelThreeItem(self.glb, self.child_count, self.comm_id, self.thread_id, query.value(0), query.value(1), query.value(2), query.value(3), int(query.value(4)), int(query.value(5)), self)
483 self.child_items.append(child_item)
484 self.child_count += 1
485
486# Context-sensitive call graph data model level three item
487
488class CallGraphLevelThreeItem(CallGraphLevelTwoPlusItemBase):
489
490 def __init__(self, glb, row, comm_id, thread_id, call_path_id, name, dso, count, time, branch_count, parent_item):
491 super(CallGraphLevelThreeItem, self).__init__(glb, row, comm_id, thread_id, call_path_id, time, branch_count, parent_item)
492 dso = dsoname(dso)
493 self.data = [ name, dso, str(count), str(time), PercentToOneDP(time, parent_item.time), str(branch_count), PercentToOneDP(branch_count, parent_item.branch_count) ]
494 self.dbid = call_path_id
495
496# Context-sensitive call graph data model level two item
497
498class CallGraphLevelTwoItem(CallGraphLevelTwoPlusItemBase):
499
500 def __init__(self, glb, row, comm_id, thread_id, pid, tid, parent_item):
501 super(CallGraphLevelTwoItem, self).__init__(glb, row, comm_id, thread_id, 1, 0, 0, parent_item)
502 self.data = [str(pid) + ":" + str(tid), "", "", "", "", "", ""]
503 self.dbid = thread_id
504
505 def Select(self):
506 super(CallGraphLevelTwoItem, self).Select()
507 for child_item in self.child_items:
508 self.time += child_item.time
509 self.branch_count += child_item.branch_count
510 for child_item in self.child_items:
511 child_item.data[4] = PercentToOneDP(child_item.time, self.time)
512 child_item.data[6] = PercentToOneDP(child_item.branch_count, self.branch_count)
513
514# Context-sensitive call graph data model level one item
515
516class CallGraphLevelOneItem(CallGraphLevelItemBase):
517
518 def __init__(self, glb, row, comm_id, comm, parent_item):
519 super(CallGraphLevelOneItem, self).__init__(glb, row, parent_item)
520 self.data = [comm, "", "", "", "", "", ""]
521 self.dbid = comm_id
522
523 def Select(self):
524 self.query_done = True;
525 query = QSqlQuery(self.glb.db)
526 QueryExec(query, "SELECT thread_id, pid, tid"
527 " FROM comm_threads"
528 " INNER JOIN threads ON thread_id = threads.id"
529 " WHERE comm_id = " + str(self.dbid))
530 while query.next():
531 child_item = CallGraphLevelTwoItem(self.glb, self.child_count, self.dbid, query.value(0), query.value(1), query.value(2), self)
532 self.child_items.append(child_item)
533 self.child_count += 1
534
535# Context-sensitive call graph data model root item
536
537class CallGraphRootItem(CallGraphLevelItemBase):
538
539 def __init__(self, glb):
540 super(CallGraphRootItem, self).__init__(glb, 0, None)
541 self.dbid = 0
542 self.query_done = True;
543 query = QSqlQuery(glb.db)
544 QueryExec(query, "SELECT id, comm FROM comms")
545 while query.next():
546 if not query.value(0):
547 continue
548 child_item = CallGraphLevelOneItem(glb, self.child_count, query.value(0), query.value(1), self)
549 self.child_items.append(child_item)
550 self.child_count += 1
551
552# Context-sensitive call graph data model
553
554class CallGraphModel(TreeModel):
555
556 def __init__(self, glb, parent=None):
557 super(CallGraphModel, self).__init__(CallGraphRootItem(glb), parent)
558 self.glb = glb
559
560 def columnCount(self, parent=None):
561 return 7
562
563 def columnHeader(self, column):
564 headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]
565 return headers[column]
566
567 def columnAlignment(self, column):
568 alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ]
569 return alignment[column]
570
571 def FindSelect(self, value, pattern, query):
572 if pattern:
573 # postgresql and sqlite pattern patching differences:
574 # postgresql LIKE is case sensitive but sqlite LIKE is not
575 # postgresql LIKE allows % and _ to be escaped with \ but sqlite LIKE does not
576 # postgresql supports ILIKE which is case insensitive
577 # sqlite supports GLOB (text only) which uses * and ? and is case sensitive
578 if not self.glb.dbref.is_sqlite3:
579 # Escape % and _
580 s = value.replace("%", "\%")
581 s = s.replace("_", "\_")
582 # Translate * and ? into SQL LIKE pattern characters % and _
583 trans = string.maketrans("*?", "%_")
584 match = " LIKE '" + str(s).translate(trans) + "'"
585 else:
586 match = " GLOB '" + str(value) + "'"
587 else:
588 match = " = '" + str(value) + "'"
589 QueryExec(query, "SELECT call_path_id, comm_id, thread_id"
590 " FROM calls"
591 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
592 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
593 " WHERE symbols.name" + match +
594 " GROUP BY comm_id, thread_id, call_path_id"
595 " ORDER BY comm_id, thread_id, call_path_id")
596
597 def FindPath(self, query):
598 # Turn the query result into a list of ids that the tree view can walk
599 # to open the tree at the right place.
600 ids = []
601 parent_id = query.value(0)
602 while parent_id:
603 ids.insert(0, parent_id)
604 q2 = QSqlQuery(self.glb.db)
605 QueryExec(q2, "SELECT parent_id"
606 " FROM call_paths"
607 " WHERE id = " + str(parent_id))
608 if not q2.next():
609 break
610 parent_id = q2.value(0)
611 # The call path root is not used
612 if ids[0] == 1:
613 del ids[0]
614 ids.insert(0, query.value(2))
615 ids.insert(0, query.value(1))
616 return ids
617
618 def Found(self, query, found):
619 if found:
620 return self.FindPath(query)
621 return []
622
623 def FindValue(self, value, pattern, query, last_value, last_pattern):
624 if last_value == value and pattern == last_pattern:
625 found = query.first()
626 else:
627 self.FindSelect(value, pattern, query)
628 found = query.next()
629 return self.Found(query, found)
630
631 def FindNext(self, query):
632 found = query.next()
633 if not found:
634 found = query.first()
635 return self.Found(query, found)
636
637 def FindPrev(self, query):
638 found = query.previous()
639 if not found:
640 found = query.last()
641 return self.Found(query, found)
642
643 def FindThread(self, c):
644 if c.direction == 0 or c.value != c.last_value or c.pattern != c.last_pattern:
645 ids = self.FindValue(c.value, c.pattern, c.query, c.last_value, c.last_pattern)
646 elif c.direction > 0:
647 ids = self.FindNext(c.query)
648 else:
649 ids = self.FindPrev(c.query)
650 return (True, ids)
651
652 def Find(self, value, direction, pattern, context, callback):
653 class Context():
654 def __init__(self, *x):
655 self.value, self.direction, self.pattern, self.query, self.last_value, self.last_pattern = x
656 def Update(self, *x):
657 self.value, self.direction, self.pattern, self.last_value, self.last_pattern = x + (self.value, self.pattern)
658 if len(context):
659 context[0].Update(value, direction, pattern)
660 else:
661 context.append(Context(value, direction, pattern, QSqlQuery(self.glb.db), None, None))
662 # Use a thread so the UI is not blocked during the SELECT
663 thread = Thread(self.FindThread, context[0])
664 thread.done.connect(lambda ids, t=thread, c=callback: self.FindDone(t, c, ids), Qt.QueuedConnection)
665 thread.start()
666
667 def FindDone(self, thread, callback, ids):
668 callback(ids)
669
670# Vertical widget layout
671
672class VBox():
673
674 def __init__(self, w1, w2, w3=None):
675 self.vbox = QWidget()
676 self.vbox.setLayout(QVBoxLayout());
677
678 self.vbox.layout().setContentsMargins(0, 0, 0, 0)
679
680 self.vbox.layout().addWidget(w1)
681 self.vbox.layout().addWidget(w2)
682 if w3:
683 self.vbox.layout().addWidget(w3)
684
685 def Widget(self):
686 return self.vbox
687
688# Context-sensitive call graph window
689
690class CallGraphWindow(QMdiSubWindow):
691
692 def __init__(self, glb, parent=None):
693 super(CallGraphWindow, self).__init__(parent)
694
695 self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x))
696
697 self.view = QTreeView()
698 self.view.setModel(self.model)
699
700 for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)):
701 self.view.setColumnWidth(c, w)
702
703 self.find_bar = FindBar(self, self)
704
705 self.vbox = VBox(self.view, self.find_bar.Widget())
706
707 self.setWidget(self.vbox.Widget())
708
709 AddSubWindow(glb.mainwindow.mdi_area, self, "Context-Sensitive Call Graph")
710
711 def DisplayFound(self, ids):
712 if not len(ids):
713 return False
714 parent = QModelIndex()
715 for dbid in ids:
716 found = False
717 n = self.model.rowCount(parent)
718 for row in xrange(n):
719 child = self.model.index(row, 0, parent)
720 if child.internalPointer().dbid == dbid:
721 found = True
722 self.view.setCurrentIndex(child)
723 parent = child
724 break
725 if not found:
726 break
727 return found
728
729 def Find(self, value, direction, pattern, context):
730 self.view.setFocus()
731 self.find_bar.Busy()
732 self.model.Find(value, direction, pattern, context, self.FindDone)
733
734 def FindDone(self, ids):
735 found = True
736 if not self.DisplayFound(ids):
737 found = False
738 self.find_bar.Idle()
739 if not found:
740 self.find_bar.NotFound()
741
742# Child data item finder
743
744class ChildDataItemFinder():
745
746 def __init__(self, root):
747 self.root = root
748 self.value, self.direction, self.pattern, self.last_value, self.last_pattern = (None,) * 5
749 self.rows = []
750 self.pos = 0
751
752 def FindSelect(self):
753 self.rows = []
754 if self.pattern:
755 pattern = re.compile(self.value)
756 for child in self.root.child_items:
757 for column_data in child.data:
758 if re.search(pattern, str(column_data)) is not None:
759 self.rows.append(child.row)
760 break
761 else:
762 for child in self.root.child_items:
763 for column_data in child.data:
764 if self.value in str(column_data):
765 self.rows.append(child.row)
766 break
767
768 def FindValue(self):
769 self.pos = 0
770 if self.last_value != self.value or self.pattern != self.last_pattern:
771 self.FindSelect()
772 if not len(self.rows):
773 return -1
774 return self.rows[self.pos]
775
776 def FindThread(self):
777 if self.direction == 0 or self.value != self.last_value or self.pattern != self.last_pattern:
778 row = self.FindValue()
779 elif len(self.rows):
780 if self.direction > 0:
781 self.pos += 1
782 if self.pos >= len(self.rows):
783 self.pos = 0
784 else:
785 self.pos -= 1
786 if self.pos < 0:
787 self.pos = len(self.rows) - 1
788 row = self.rows[self.pos]
789 else:
790 row = -1
791 return (True, row)
792
793 def Find(self, value, direction, pattern, context, callback):
794 self.value, self.direction, self.pattern, self.last_value, self.last_pattern = (value, direction,pattern, self.value, self.pattern)
795 # Use a thread so the UI is not blocked
796 thread = Thread(self.FindThread)
797 thread.done.connect(lambda row, t=thread, c=callback: self.FindDone(t, c, row), Qt.QueuedConnection)
798 thread.start()
799
800 def FindDone(self, thread, callback, row):
801 callback(row)
802
803# Number of database records to fetch in one go
804
805glb_chunk_sz = 10000
806
807# size of pickled integer big enough for record size
808
809glb_nsz = 8
810
811# Background process for SQL data fetcher
812
813class SQLFetcherProcess():
814
815 def __init__(self, dbref, sql, buffer, head, tail, fetch_count, fetching_done, process_target, wait_event, fetched_event, prep):
816 # Need a unique connection name
817 conn_name = "SQLFetcher" + str(os.getpid())
818 self.db, dbname = dbref.Open(conn_name)
819 self.sql = sql
820 self.buffer = buffer
821 self.head = head
822 self.tail = tail
823 self.fetch_count = fetch_count
824 self.fetching_done = fetching_done
825 self.process_target = process_target
826 self.wait_event = wait_event
827 self.fetched_event = fetched_event
828 self.prep = prep
829 self.query = QSqlQuery(self.db)
830 self.query_limit = 0 if "$$last_id$$" in sql else 2
831 self.last_id = -1
832 self.fetched = 0
833 self.more = True
834 self.local_head = self.head.value
835 self.local_tail = self.tail.value
836
837 def Select(self):
838 if self.query_limit:
839 if self.query_limit == 1:
840 return
841 self.query_limit -= 1
842 stmt = self.sql.replace("$$last_id$$", str(self.last_id))
843 QueryExec(self.query, stmt)
844
845 def Next(self):
846 if not self.query.next():
847 self.Select()
848 if not self.query.next():
849 return None
850 self.last_id = self.query.value(0)
851 return self.prep(self.query)
852
853 def WaitForTarget(self):
854 while True:
855 self.wait_event.clear()
856 target = self.process_target.value
857 if target > self.fetched or target < 0:
858 break
859 self.wait_event.wait()
860 return target
861
862 def HasSpace(self, sz):
863 if self.local_tail <= self.local_head:
864 space = len(self.buffer) - self.local_head
865 if space > sz:
866 return True
867 if space >= glb_nsz:
868 # Use 0 (or space < glb_nsz) to mean there is no more at the top of the buffer
869 nd = cPickle.dumps(0, cPickle.HIGHEST_PROTOCOL)
870 self.buffer[self.local_head : self.local_head + len(nd)] = nd
871 self.local_head = 0
872 if self.local_tail - self.local_head > sz:
873 return True
874 return False
875
876 def WaitForSpace(self, sz):
877 if self.HasSpace(sz):
878 return
879 while True:
880 self.wait_event.clear()
881 self.local_tail = self.tail.value
882 if self.HasSpace(sz):
883 return
884 self.wait_event.wait()
885
886 def AddToBuffer(self, obj):
887 d = cPickle.dumps(obj, cPickle.HIGHEST_PROTOCOL)
888 n = len(d)
889 nd = cPickle.dumps(n, cPickle.HIGHEST_PROTOCOL)
890 sz = n + glb_nsz
891 self.WaitForSpace(sz)
892 pos = self.local_head
893 self.buffer[pos : pos + len(nd)] = nd
894 self.buffer[pos + glb_nsz : pos + sz] = d
895 self.local_head += sz
896
897 def FetchBatch(self, batch_size):
898 fetched = 0
899 while batch_size > fetched:
900 obj = self.Next()
901 if obj is None:
902 self.more = False
903 break
904 self.AddToBuffer(obj)
905 fetched += 1
906 if fetched:
907 self.fetched += fetched
908 with self.fetch_count.get_lock():
909 self.fetch_count.value += fetched
910 self.head.value = self.local_head
911 self.fetched_event.set()
912
913 def Run(self):
914 while self.more:
915 target = self.WaitForTarget()
916 if target < 0:
917 break
918 batch_size = min(glb_chunk_sz, target - self.fetched)
919 self.FetchBatch(batch_size)
920 self.fetching_done.value = True
921 self.fetched_event.set()
922
923def SQLFetcherFn(*x):
924 process = SQLFetcherProcess(*x)
925 process.Run()
926
927# SQL data fetcher
928
929class SQLFetcher(QObject):
930
931 done = Signal(object)
932
933 def __init__(self, glb, sql, prep, process_data, parent=None):
934 super(SQLFetcher, self).__init__(parent)
935 self.process_data = process_data
936 self.more = True
937 self.target = 0
938 self.last_target = 0
939 self.fetched = 0
940 self.buffer_size = 16 * 1024 * 1024
941 self.buffer = Array(c_char, self.buffer_size, lock=False)
942 self.head = Value(c_longlong)
943 self.tail = Value(c_longlong)
944 self.local_tail = 0
945 self.fetch_count = Value(c_longlong)
946 self.fetching_done = Value(c_bool)
947 self.last_count = 0
948 self.process_target = Value(c_longlong)
949 self.wait_event = Event()
950 self.fetched_event = Event()
951 glb.AddInstanceToShutdownOnExit(self)
952 self.process = Process(target=SQLFetcherFn, args=(glb.dbref, sql, self.buffer, self.head, self.tail, self.fetch_count, self.fetching_done, self.process_target, self.wait_event, self.fetched_event, prep))
953 self.process.start()
954 self.thread = Thread(self.Thread)
955 self.thread.done.connect(self.ProcessData, Qt.QueuedConnection)
956 self.thread.start()
957
958 def Shutdown(self):
959 # Tell the thread and process to exit
960 self.process_target.value = -1
961 self.wait_event.set()
962 self.more = False
963 self.fetching_done.value = True
964 self.fetched_event.set()
965
966 def Thread(self):
967 if not self.more:
968 return True, 0
969 while True:
970 self.fetched_event.clear()
971 fetch_count = self.fetch_count.value
972 if fetch_count != self.last_count:
973 break
974 if self.fetching_done.value:
975 self.more = False
976 return True, 0
977 self.fetched_event.wait()
978 count = fetch_count - self.last_count
979 self.last_count = fetch_count
980 self.fetched += count
981 return False, count
982
983 def Fetch(self, nr):
984 if not self.more:
985 # -1 inidcates there are no more
986 return -1
987 result = self.fetched
988 extra = result + nr - self.target
989 if extra > 0:
990 self.target += extra
991 # process_target < 0 indicates shutting down
992 if self.process_target.value >= 0:
993 self.process_target.value = self.target
994 self.wait_event.set()
995 return result
996
997 def RemoveFromBuffer(self):
998 pos = self.local_tail
999 if len(self.buffer) - pos < glb_nsz:
1000 pos = 0
1001 n = cPickle.loads(self.buffer[pos : pos + glb_nsz])
1002 if n == 0:
1003 pos = 0
1004 n = cPickle.loads(self.buffer[0 : glb_nsz])
1005 pos += glb_nsz
1006 obj = cPickle.loads(self.buffer[pos : pos + n])
1007 self.local_tail = pos + n
1008 return obj
1009
1010 def ProcessData(self, count):
1011 for i in xrange(count):
1012 obj = self.RemoveFromBuffer()
1013 self.process_data(obj)
1014 self.tail.value = self.local_tail
1015 self.wait_event.set()
1016 self.done.emit(count)
1017
1018# Fetch more records bar
1019
1020class FetchMoreRecordsBar():
1021
1022 def __init__(self, model, parent):
1023 self.model = model
1024
1025 self.label = QLabel("Number of records (x " + "{:,}".format(glb_chunk_sz) + ") to fetch:")
1026 self.label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
1027
1028 self.fetch_count = QSpinBox()
1029 self.fetch_count.setRange(1, 1000000)
1030 self.fetch_count.setValue(10)
1031 self.fetch_count.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
1032
1033 self.fetch = QPushButton("Go!")
1034 self.fetch.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
1035 self.fetch.released.connect(self.FetchMoreRecords)
1036
1037 self.progress = QProgressBar()
1038 self.progress.setRange(0, 100)
1039 self.progress.hide()
1040
1041 self.done_label = QLabel("All records fetched")
1042 self.done_label.hide()
1043
1044 self.spacer = QLabel("")
1045
1046 self.close_button = QToolButton()
1047 self.close_button.setIcon(parent.style().standardIcon(QStyle.SP_DockWidgetCloseButton))
1048 self.close_button.released.connect(self.Deactivate)
1049
1050 self.hbox = QHBoxLayout()
1051 self.hbox.setContentsMargins(0, 0, 0, 0)
1052
1053 self.hbox.addWidget(self.label)
1054 self.hbox.addWidget(self.fetch_count)
1055 self.hbox.addWidget(self.fetch)
1056 self.hbox.addWidget(self.spacer)
1057 self.hbox.addWidget(self.progress)
1058 self.hbox.addWidget(self.done_label)
1059 self.hbox.addWidget(self.close_button)
1060
1061 self.bar = QWidget()
1062 self.bar.setLayout(self.hbox);
1063 self.bar.show()
1064
1065 self.in_progress = False
1066 self.model.progress.connect(self.Progress)
1067
1068 self.done = False
1069
1070 if not model.HasMoreRecords():
1071 self.Done()
1072
1073 def Widget(self):
1074 return self.bar
1075
1076 def Activate(self):
1077 self.bar.show()
1078 self.fetch.setFocus()
1079
1080 def Deactivate(self):
1081 self.bar.hide()
1082
1083 def Enable(self, enable):
1084 self.fetch.setEnabled(enable)
1085 self.fetch_count.setEnabled(enable)
1086
1087 def Busy(self):
1088 self.Enable(False)
1089 self.fetch.hide()
1090 self.spacer.hide()
1091 self.progress.show()
1092
1093 def Idle(self):
1094 self.in_progress = False
1095 self.Enable(True)
1096 self.progress.hide()
1097 self.fetch.show()
1098 self.spacer.show()
1099
1100 def Target(self):
1101 return self.fetch_count.value() * glb_chunk_sz
1102
1103 def Done(self):
1104 self.done = True
1105 self.Idle()
1106 self.label.hide()
1107 self.fetch_count.hide()
1108 self.fetch.hide()
1109 self.spacer.hide()
1110 self.done_label.show()
1111
1112 def Progress(self, count):
1113 if self.in_progress:
1114 if count:
1115 percent = ((count - self.start) * 100) / self.Target()
1116 if percent >= 100:
1117 self.Idle()
1118 else:
1119 self.progress.setValue(percent)
1120 if not count:
1121 # Count value of zero means no more records
1122 self.Done()
1123
1124 def FetchMoreRecords(self):
1125 if self.done:
1126 return
1127 self.progress.setValue(0)
1128 self.Busy()
1129 self.in_progress = True
1130 self.start = self.model.FetchMoreRecords(self.Target())
1131
1132# Brance data model level two item
1133
1134class BranchLevelTwoItem():
1135
1136 def __init__(self, row, text, parent_item):
1137 self.row = row
1138 self.parent_item = parent_item
1139 self.data = [""] * 8
1140 self.data[7] = text
1141 self.level = 2
1142
1143 def getParentItem(self):
1144 return self.parent_item
1145
1146 def getRow(self):
1147 return self.row
1148
1149 def childCount(self):
1150 return 0
1151
1152 def hasChildren(self):
1153 return False
1154
1155 def getData(self, column):
1156 return self.data[column]
1157
1158# Brance data model level one item
1159
1160class BranchLevelOneItem():
1161
1162 def __init__(self, glb, row, data, parent_item):
1163 self.glb = glb
1164 self.row = row
1165 self.parent_item = parent_item
1166 self.child_count = 0
1167 self.child_items = []
1168 self.data = data[1:]
1169 self.dbid = data[0]
1170 self.level = 1
1171 self.query_done = False
1172
1173 def getChildItem(self, row):
1174 return self.child_items[row]
1175
1176 def getParentItem(self):
1177 return self.parent_item
1178
1179 def getRow(self):
1180 return self.row
1181
1182 def Select(self):
1183 self.query_done = True
1184
1185 if not self.glb.have_disassembler:
1186 return
1187
1188 query = QSqlQuery(self.glb.db)
1189
1190 QueryExec(query, "SELECT cpu, to_dso_id, to_symbol_id, to_sym_offset, short_name, long_name, build_id, sym_start, to_ip"
1191 " FROM samples"
1192 " INNER JOIN dsos ON samples.to_dso_id = dsos.id"
1193 " INNER JOIN symbols ON samples.to_symbol_id = symbols.id"
1194 " WHERE samples.id = " + str(self.dbid))
1195 if not query.next():
1196 return
1197 cpu = query.value(0)
1198 dso = query.value(1)
1199 sym = query.value(2)
1200 if dso == 0 or sym == 0:
1201 return
1202 off = query.value(3)
1203 short_name = query.value(4)
1204 long_name = query.value(5)
1205 build_id = query.value(6)
1206 sym_start = query.value(7)
1207 ip = query.value(8)
1208
1209 QueryExec(query, "SELECT samples.dso_id, symbol_id, sym_offset, sym_start"
1210 " FROM samples"
1211 " INNER JOIN symbols ON samples.symbol_id = symbols.id"
1212 " WHERE samples.id > " + str(self.dbid) + " AND cpu = " + str(cpu) +
1213 " ORDER BY samples.id"
1214 " LIMIT 1")
1215 if not query.next():
1216 return
1217 if query.value(0) != dso:
1218 # Cannot disassemble from one dso to another
1219 return
1220 bsym = query.value(1)
1221 boff = query.value(2)
1222 bsym_start = query.value(3)
1223 if bsym == 0:
1224 return
1225 tot = bsym_start + boff + 1 - sym_start - off
1226 if tot <= 0 or tot > 16384:
1227 return
1228
1229 inst = self.glb.disassembler.Instruction()
1230 f = self.glb.FileFromNamesAndBuildId(short_name, long_name, build_id)
1231 if not f:
1232 return
1233 mode = 0 if Is64Bit(f) else 1
1234 self.glb.disassembler.SetMode(inst, mode)
1235
1236 buf_sz = tot + 16
1237 buf = create_string_buffer(tot + 16)
1238 f.seek(sym_start + off)
1239 buf.value = f.read(buf_sz)
1240 buf_ptr = addressof(buf)
1241 i = 0
1242 while tot > 0:
1243 cnt, text = self.glb.disassembler.DisassembleOne(inst, buf_ptr, buf_sz, ip)
1244 if cnt:
1245 byte_str = tohex(ip).rjust(16)
1246 for k in xrange(cnt):
1247 byte_str += " %02x" % ord(buf[i])
1248 i += 1
1249 while k < 15:
1250 byte_str += " "
1251 k += 1
1252 self.child_items.append(BranchLevelTwoItem(0, byte_str + " " + text, self))
1253 self.child_count += 1
1254 else:
1255 return
1256 buf_ptr += cnt
1257 tot -= cnt
1258 buf_sz -= cnt
1259 ip += cnt
1260
1261 def childCount(self):
1262 if not self.query_done:
1263 self.Select()
1264 if not self.child_count:
1265 return -1
1266 return self.child_count
1267
1268 def hasChildren(self):
1269 if not self.query_done:
1270 return True
1271 return self.child_count > 0
1272
1273 def getData(self, column):
1274 return self.data[column]
1275
1276# Brance data model root item
1277
1278class BranchRootItem():
1279
1280 def __init__(self):
1281 self.child_count = 0
1282 self.child_items = []
1283 self.level = 0
1284
1285 def getChildItem(self, row):
1286 return self.child_items[row]
1287
1288 def getParentItem(self):
1289 return None
1290
1291 def getRow(self):
1292 return 0
1293
1294 def childCount(self):
1295 return self.child_count
1296
1297 def hasChildren(self):
1298 return self.child_count > 0
1299
1300 def getData(self, column):
1301 return ""
1302
1303# Branch data preparation
1304
1305def BranchDataPrep(query):
1306 data = []
1307 for i in xrange(0, 8):
1308 data.append(query.value(i))
1309 data.append(tohex(query.value(8)).rjust(16) + " " + query.value(9) + offstr(query.value(10)) +
1310 " (" + dsoname(query.value(11)) + ")" + " -> " +
1311 tohex(query.value(12)) + " " + query.value(13) + offstr(query.value(14)) +
1312 " (" + dsoname(query.value(15)) + ")")
1313 return data
1314
1315# Branch data model
1316
1317class BranchModel(TreeModel):
1318
1319 progress = Signal(object)
1320
1321 def __init__(self, glb, event_id, where_clause, parent=None):
1322 super(BranchModel, self).__init__(BranchRootItem(), parent)
1323 self.glb = glb
1324 self.event_id = event_id
1325 self.more = True
1326 self.populated = 0
1327 sql = ("SELECT samples.id, time, cpu, comm, pid, tid, branch_types.name,"
1328 " CASE WHEN in_tx = '0' THEN 'No' ELSE 'Yes' END,"
1329 " ip, symbols.name, sym_offset, dsos.short_name,"
1330 " to_ip, to_symbols.name, to_sym_offset, to_dsos.short_name"
1331 " FROM samples"
1332 " INNER JOIN comms ON comm_id = comms.id"
1333 " INNER JOIN threads ON thread_id = threads.id"
1334 " INNER JOIN branch_types ON branch_type = branch_types.id"
1335 " INNER JOIN symbols ON symbol_id = symbols.id"
1336 " INNER JOIN symbols to_symbols ON to_symbol_id = to_symbols.id"
1337 " INNER JOIN dsos ON samples.dso_id = dsos.id"
1338 " INNER JOIN dsos AS to_dsos ON samples.to_dso_id = to_dsos.id"
1339 " WHERE samples.id > $$last_id$$" + where_clause +
1340 " AND evsel_id = " + str(self.event_id) +
1341 " ORDER BY samples.id"
1342 " LIMIT " + str(glb_chunk_sz))
1343 self.fetcher = SQLFetcher(glb, sql, BranchDataPrep, self.AddSample)
1344 self.fetcher.done.connect(self.Update)
1345 self.fetcher.Fetch(glb_chunk_sz)
1346
1347 def columnCount(self, parent=None):
1348 return 8
1349
1350 def columnHeader(self, column):
1351 return ("Time", "CPU", "Command", "PID", "TID", "Branch Type", "In Tx", "Branch")[column]
1352
1353 def columnFont(self, column):
1354 if column != 7:
1355 return None
1356 return QFont("Monospace")
1357
1358 def DisplayData(self, item, index):
1359 if item.level == 1:
1360 self.FetchIfNeeded(item.row)
1361 return item.getData(index.column())
1362
1363 def AddSample(self, data):
1364 child = BranchLevelOneItem(self.glb, self.populated, data, self.root)
1365 self.root.child_items.append(child)
1366 self.populated += 1
1367
1368 def Update(self, fetched):
1369 if not fetched:
1370 self.more = False
1371 self.progress.emit(0)
1372 child_count = self.root.child_count
1373 count = self.populated - child_count
1374 if count > 0:
1375 parent = QModelIndex()
1376 self.beginInsertRows(parent, child_count, child_count + count - 1)
1377 self.insertRows(child_count, count, parent)
1378 self.root.child_count += count
1379 self.endInsertRows()
1380 self.progress.emit(self.root.child_count)
1381
1382 def FetchMoreRecords(self, count):
1383 current = self.root.child_count
1384 if self.more:
1385 self.fetcher.Fetch(count)
1386 else:
1387 self.progress.emit(0)
1388 return current
1389
1390 def HasMoreRecords(self):
1391 return self.more
1392
1393# Branch window
1394
1395class BranchWindow(QMdiSubWindow):
1396
1397 def __init__(self, glb, event_id, name, where_clause, parent=None):
1398 super(BranchWindow, self).__init__(parent)
1399
1400 model_name = "Branch Events " + str(event_id)
1401 if len(where_clause):
1402 model_name = where_clause + " " + model_name
1403
1404 self.model = LookupCreateModel(model_name, lambda: BranchModel(glb, event_id, where_clause))
1405
1406 self.view = QTreeView()
1407 self.view.setUniformRowHeights(True)
1408 self.view.setModel(self.model)
1409
1410 self.ResizeColumnsToContents()
1411
1412 self.find_bar = FindBar(self, self, True)
1413
1414 self.finder = ChildDataItemFinder(self.model.root)
1415
1416 self.fetch_bar = FetchMoreRecordsBar(self.model, self)
1417
1418 self.vbox = VBox(self.view, self.find_bar.Widget(), self.fetch_bar.Widget())
1419
1420 self.setWidget(self.vbox.Widget())
1421
1422 AddSubWindow(glb.mainwindow.mdi_area, self, name + " Branch Events")
1423
1424 def ResizeColumnToContents(self, column, n):
1425 # Using the view's resizeColumnToContents() here is extrememly slow
1426 # so implement a crude alternative
1427 mm = "MM" if column else "MMMM"
1428 font = self.view.font()
1429 metrics = QFontMetrics(font)
1430 max = 0
1431 for row in xrange(n):
1432 val = self.model.root.child_items[row].data[column]
1433 len = metrics.width(str(val) + mm)
1434 max = len if len > max else max
1435 val = self.model.columnHeader(column)
1436 len = metrics.width(str(val) + mm)
1437 max = len if len > max else max
1438 self.view.setColumnWidth(column, max)
1439
1440 def ResizeColumnsToContents(self):
1441 n = min(self.model.root.child_count, 100)
1442 if n < 1:
1443 # No data yet, so connect a signal to notify when there is
1444 self.model.rowsInserted.connect(self.UpdateColumnWidths)
1445 return
1446 columns = self.model.columnCount()
1447 for i in xrange(columns):
1448 self.ResizeColumnToContents(i, n)
1449
1450 def UpdateColumnWidths(self, *x):
1451 # This only needs to be done once, so disconnect the signal now
1452 self.model.rowsInserted.disconnect(self.UpdateColumnWidths)
1453 self.ResizeColumnsToContents()
1454
1455 def Find(self, value, direction, pattern, context):
1456 self.view.setFocus()
1457 self.find_bar.Busy()
1458 self.finder.Find(value, direction, pattern, context, self.FindDone)
1459
1460 def FindDone(self, row):
1461 self.find_bar.Idle()
1462 if row >= 0:
1463 self.view.setCurrentIndex(self.model.index(row, 0, QModelIndex()))
1464 else:
1465 self.find_bar.NotFound()
1466
1467# Event list
1468
1469def GetEventList(db):
1470 events = []
1471 query = QSqlQuery(db)
1472 QueryExec(query, "SELECT name FROM selected_events WHERE id > 0 ORDER BY id")
1473 while query.next():
1474 events.append(query.value(0))
1475 return events
1476
1477# SQL data preparation
1478
1479def SQLTableDataPrep(query, count):
1480 data = []
1481 for i in xrange(count):
1482 data.append(query.value(i))
1483 return data
1484
1485# SQL table data model item
1486
1487class SQLTableItem():
1488
1489 def __init__(self, row, data):
1490 self.row = row
1491 self.data = data
1492
1493 def getData(self, column):
1494 return self.data[column]
1495
1496# SQL table data model
1497
1498class SQLTableModel(TableModel):
1499
1500 progress = Signal(object)
1501
1502 def __init__(self, glb, sql, column_count, parent=None):
1503 super(SQLTableModel, self).__init__(parent)
1504 self.glb = glb
1505 self.more = True
1506 self.populated = 0
1507 self.fetcher = SQLFetcher(glb, sql, lambda x, y=column_count: SQLTableDataPrep(x, y), self.AddSample)
1508 self.fetcher.done.connect(self.Update)
1509 self.fetcher.Fetch(glb_chunk_sz)
1510
1511 def DisplayData(self, item, index):
1512 self.FetchIfNeeded(item.row)
1513 return item.getData(index.column())
1514
1515 def AddSample(self, data):
1516 child = SQLTableItem(self.populated, data)
1517 self.child_items.append(child)
1518 self.populated += 1
1519
1520 def Update(self, fetched):
1521 if not fetched:
1522 self.more = False
1523 self.progress.emit(0)
1524 child_count = self.child_count
1525 count = self.populated - child_count
1526 if count > 0:
1527 parent = QModelIndex()
1528 self.beginInsertRows(parent, child_count, child_count + count - 1)
1529 self.insertRows(child_count, count, parent)
1530 self.child_count += count
1531 self.endInsertRows()
1532 self.progress.emit(self.child_count)
1533
1534 def FetchMoreRecords(self, count):
1535 current = self.child_count
1536 if self.more:
1537 self.fetcher.Fetch(count)
1538 else:
1539 self.progress.emit(0)
1540 return current
1541
1542 def HasMoreRecords(self):
1543 return self.more
1544
1545# SQL automatic table data model
1546
1547class SQLAutoTableModel(SQLTableModel):
1548
1549 def __init__(self, glb, table_name, parent=None):
1550 sql = "SELECT * FROM " + table_name + " WHERE id > $$last_id$$ ORDER BY id LIMIT " + str(glb_chunk_sz)
1551 if table_name == "comm_threads_view":
1552 # For now, comm_threads_view has no id column
1553 sql = "SELECT * FROM " + table_name + " WHERE comm_id > $$last_id$$ ORDER BY comm_id LIMIT " + str(glb_chunk_sz)
1554 self.column_headers = []
1555 query = QSqlQuery(glb.db)
1556 if glb.dbref.is_sqlite3:
1557 QueryExec(query, "PRAGMA table_info(" + table_name + ")")
1558 while query.next():
1559 self.column_headers.append(query.value(1))
1560 if table_name == "sqlite_master":
1561 sql = "SELECT * FROM " + table_name
1562 else:
1563 if table_name[:19] == "information_schema.":
1564 sql = "SELECT * FROM " + table_name
1565 select_table_name = table_name[19:]
1566 schema = "information_schema"
1567 else:
1568 select_table_name = table_name
1569 schema = "public"
1570 QueryExec(query, "SELECT column_name FROM information_schema.columns WHERE table_schema = '" + schema + "' and table_name = '" + select_table_name + "'")
1571 while query.next():
1572 self.column_headers.append(query.value(0))
1573 super(SQLAutoTableModel, self).__init__(glb, sql, len(self.column_headers), parent)
1574
1575 def columnCount(self, parent=None):
1576 return len(self.column_headers)
1577
1578 def columnHeader(self, column):
1579 return self.column_headers[column]
1580
1581# Base class for custom ResizeColumnsToContents
1582
1583class ResizeColumnsToContentsBase(QObject):
1584
1585 def __init__(self, parent=None):
1586 super(ResizeColumnsToContentsBase, self).__init__(parent)
1587
1588 def ResizeColumnToContents(self, column, n):
1589 # Using the view's resizeColumnToContents() here is extrememly slow
1590 # so implement a crude alternative
1591 font = self.view.font()
1592 metrics = QFontMetrics(font)
1593 max = 0
1594 for row in xrange(n):
1595 val = self.data_model.child_items[row].data[column]
1596 len = metrics.width(str(val) + "MM")
1597 max = len if len > max else max
1598 val = self.data_model.columnHeader(column)
1599 len = metrics.width(str(val) + "MM")
1600 max = len if len > max else max
1601 self.view.setColumnWidth(column, max)
1602
1603 def ResizeColumnsToContents(self):
1604 n = min(self.data_model.child_count, 100)
1605 if n < 1:
1606 # No data yet, so connect a signal to notify when there is
1607 self.data_model.rowsInserted.connect(self.UpdateColumnWidths)
1608 return
1609 columns = self.data_model.columnCount()
1610 for i in xrange(columns):
1611 self.ResizeColumnToContents(i, n)
1612
1613 def UpdateColumnWidths(self, *x):
1614 # This only needs to be done once, so disconnect the signal now
1615 self.data_model.rowsInserted.disconnect(self.UpdateColumnWidths)
1616 self.ResizeColumnsToContents()
1617
1618# Table window
1619
1620class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase):
1621
1622 def __init__(self, glb, table_name, parent=None):
1623 super(TableWindow, self).__init__(parent)
1624
1625 self.data_model = LookupCreateModel(table_name + " Table", lambda: SQLAutoTableModel(glb, table_name))
1626
1627 self.model = QSortFilterProxyModel()
1628 self.model.setSourceModel(self.data_model)
1629
1630 self.view = QTableView()
1631 self.view.setModel(self.model)
1632 self.view.setEditTriggers(QAbstractItemView.NoEditTriggers)
1633 self.view.verticalHeader().setVisible(False)
1634 self.view.sortByColumn(-1, Qt.AscendingOrder)
1635 self.view.setSortingEnabled(True)
1636
1637 self.ResizeColumnsToContents()
1638
1639 self.find_bar = FindBar(self, self, True)
1640
1641 self.finder = ChildDataItemFinder(self.data_model)
1642
1643 self.fetch_bar = FetchMoreRecordsBar(self.data_model, self)
1644
1645 self.vbox = VBox(self.view, self.find_bar.Widget(), self.fetch_bar.Widget())
1646
1647 self.setWidget(self.vbox.Widget())
1648
1649 AddSubWindow(glb.mainwindow.mdi_area, self, table_name + " Table")
1650
1651 def Find(self, value, direction, pattern, context):
1652 self.view.setFocus()
1653 self.find_bar.Busy()
1654 self.finder.Find(value, direction, pattern, context, self.FindDone)
1655
1656 def FindDone(self, row):
1657 self.find_bar.Idle()
1658 if row >= 0:
1659 self.view.setCurrentIndex(self.model.index(row, 0, QModelIndex()))
1660 else:
1661 self.find_bar.NotFound()
1662
1663# Table list
1664
1665def GetTableList(glb):
1666 tables = []
1667 query = QSqlQuery(glb.db)
1668 if glb.dbref.is_sqlite3:
1669 QueryExec(query, "SELECT name FROM sqlite_master WHERE type IN ( 'table' , 'view' ) ORDER BY name")
1670 else:
1671 QueryExec(query, "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_type IN ( 'BASE TABLE' , 'VIEW' ) ORDER BY table_name")
1672 while query.next():
1673 tables.append(query.value(0))
1674 if glb.dbref.is_sqlite3:
1675 tables.append("sqlite_master")
1676 else:
1677 tables.append("information_schema.tables")
1678 tables.append("information_schema.views")
1679 tables.append("information_schema.columns")
1680 return tables
1681
1682# Action Definition
1683
1684def CreateAction(label, tip, callback, parent=None, shortcut=None):
1685 action = QAction(label, parent)
1686 if shortcut != None:
1687 action.setShortcuts(shortcut)
1688 action.setStatusTip(tip)
1689 action.triggered.connect(callback)
1690 return action
1691
1692# Typical application actions
1693
1694def CreateExitAction(app, parent=None):
1695 return CreateAction("&Quit", "Exit the application", app.closeAllWindows, parent, QKeySequence.Quit)
1696
1697# Typical MDI actions
1698
1699def CreateCloseActiveWindowAction(mdi_area):
1700 return CreateAction("Cl&ose", "Close the active window", mdi_area.closeActiveSubWindow, mdi_area)
1701
1702def CreateCloseAllWindowsAction(mdi_area):
1703 return CreateAction("Close &All", "Close all the windows", mdi_area.closeAllSubWindows, mdi_area)
1704
1705def CreateTileWindowsAction(mdi_area):
1706 return CreateAction("&Tile", "Tile the windows", mdi_area.tileSubWindows, mdi_area)
1707
1708def CreateCascadeWindowsAction(mdi_area):
1709 return CreateAction("&Cascade", "Cascade the windows", mdi_area.cascadeSubWindows, mdi_area)
1710
1711def CreateNextWindowAction(mdi_area):
1712 return CreateAction("Ne&xt", "Move the focus to the next window", mdi_area.activateNextSubWindow, mdi_area, QKeySequence.NextChild)
1713
1714def CreatePreviousWindowAction(mdi_area):
1715 return CreateAction("Pre&vious", "Move the focus to the previous window", mdi_area.activatePreviousSubWindow, mdi_area, QKeySequence.PreviousChild)
1716
1717# Typical MDI window menu
1718
1719class WindowMenu():
1720
1721 def __init__(self, mdi_area, menu):
1722 self.mdi_area = mdi_area
1723 self.window_menu = menu.addMenu("&Windows")
1724 self.close_active_window = CreateCloseActiveWindowAction(mdi_area)
1725 self.close_all_windows = CreateCloseAllWindowsAction(mdi_area)
1726 self.tile_windows = CreateTileWindowsAction(mdi_area)
1727 self.cascade_windows = CreateCascadeWindowsAction(mdi_area)
1728 self.next_window = CreateNextWindowAction(mdi_area)
1729 self.previous_window = CreatePreviousWindowAction(mdi_area)
1730 self.window_menu.aboutToShow.connect(self.Update)
1731
1732 def Update(self):
1733 self.window_menu.clear()
1734 sub_window_count = len(self.mdi_area.subWindowList())
1735 have_sub_windows = sub_window_count != 0
1736 self.close_active_window.setEnabled(have_sub_windows)
1737 self.close_all_windows.setEnabled(have_sub_windows)
1738 self.tile_windows.setEnabled(have_sub_windows)
1739 self.cascade_windows.setEnabled(have_sub_windows)
1740 self.next_window.setEnabled(have_sub_windows)
1741 self.previous_window.setEnabled(have_sub_windows)
1742 self.window_menu.addAction(self.close_active_window)
1743 self.window_menu.addAction(self.close_all_windows)
1744 self.window_menu.addSeparator()
1745 self.window_menu.addAction(self.tile_windows)
1746 self.window_menu.addAction(self.cascade_windows)
1747 self.window_menu.addSeparator()
1748 self.window_menu.addAction(self.next_window)
1749 self.window_menu.addAction(self.previous_window)
1750 if sub_window_count == 0:
1751 return
1752 self.window_menu.addSeparator()
1753 nr = 1
1754 for sub_window in self.mdi_area.subWindowList():
1755 label = str(nr) + " " + sub_window.name
1756 if nr < 10:
1757 label = "&" + label
1758 action = self.window_menu.addAction(label)
1759 action.setCheckable(True)
1760 action.setChecked(sub_window == self.mdi_area.activeSubWindow())
1761 action.triggered.connect(lambda x=nr: self.setActiveSubWindow(x))
1762 self.window_menu.addAction(action)
1763 nr += 1
1764
1765 def setActiveSubWindow(self, nr):
1766 self.mdi_area.setActiveSubWindow(self.mdi_area.subWindowList()[nr - 1])
1767
1768# Font resize
1769
1770def ResizeFont(widget, diff):
1771 font = widget.font()
1772 sz = font.pointSize()
1773 font.setPointSize(sz + diff)
1774 widget.setFont(font)
1775
1776def ShrinkFont(widget):
1777 ResizeFont(widget, -1)
1778
1779def EnlargeFont(widget):
1780 ResizeFont(widget, 1)
1781
1782# Unique name for sub-windows
1783
1784def NumberedWindowName(name, nr):
1785 if nr > 1:
1786 name += " <" + str(nr) + ">"
1787 return name
1788
1789def UniqueSubWindowName(mdi_area, name):
1790 nr = 1
1791 while True:
1792 unique_name = NumberedWindowName(name, nr)
1793 ok = True
1794 for sub_window in mdi_area.subWindowList():
1795 if sub_window.name == unique_name:
1796 ok = False
1797 break
1798 if ok:
1799 return unique_name
1800 nr += 1
1801
1802# Add a sub-window
1803
1804def AddSubWindow(mdi_area, sub_window, name):
1805 unique_name = UniqueSubWindowName(mdi_area, name)
1806 sub_window.setMinimumSize(200, 100)
1807 sub_window.resize(800, 600)
1808 sub_window.setWindowTitle(unique_name)
1809 sub_window.setAttribute(Qt.WA_DeleteOnClose)
1810 sub_window.setWindowIcon(sub_window.style().standardIcon(QStyle.SP_FileIcon))
1811 sub_window.name = unique_name
1812 mdi_area.addSubWindow(sub_window)
1813 sub_window.show()
1814
1815# Main window
1816
1817class MainWindow(QMainWindow):
1818
1819 def __init__(self, glb, parent=None):
1820 super(MainWindow, self).__init__(parent)
1821
1822 self.glb = glb
1823
1824 self.setWindowTitle("Exported SQL Viewer: " + glb.dbname)
1825 self.setWindowIcon(self.style().standardIcon(QStyle.SP_ComputerIcon))
1826 self.setMinimumSize(200, 100)
1827
1828 self.mdi_area = QMdiArea()
1829 self.mdi_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
1830 self.mdi_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
1831
1832 self.setCentralWidget(self.mdi_area)
1833
1834 menu = self.menuBar()
1835
1836 file_menu = menu.addMenu("&File")
1837 file_menu.addAction(CreateExitAction(glb.app, self))
1838
1839 edit_menu = menu.addMenu("&Edit")
1840 edit_menu.addAction(CreateAction("&Find...", "Find items", self.Find, self, QKeySequence.Find))
1841 edit_menu.addAction(CreateAction("Fetch &more records...", "Fetch more records", self.FetchMoreRecords, self, [QKeySequence(Qt.Key_F8)]))
1842 edit_menu.addAction(CreateAction("&Shrink Font", "Make text smaller", self.ShrinkFont, self, [QKeySequence("Ctrl+-")]))
1843 edit_menu.addAction(CreateAction("&Enlarge Font", "Make text bigger", self.EnlargeFont, self, [QKeySequence("Ctrl++")]))
1844
1845 reports_menu = menu.addMenu("&Reports")
1846 reports_menu.addAction(CreateAction("Context-Sensitive Call &Graph", "Create a new window containing a context-sensitive call graph", self.NewCallGraph, self))
1847
1848 self.EventMenu(GetEventList(glb.db), reports_menu)
1849
1850 self.TableMenu(GetTableList(glb), menu)
1851
1852 self.window_menu = WindowMenu(self.mdi_area, menu)
1853
1854 def Find(self):
1855 win = self.mdi_area.activeSubWindow()
1856 if win:
1857 try:
1858 win.find_bar.Activate()
1859 except:
1860 pass
1861
1862 def FetchMoreRecords(self):
1863 win = self.mdi_area.activeSubWindow()
1864 if win:
1865 try:
1866 win.fetch_bar.Activate()
1867 except:
1868 pass
1869
1870 def ShrinkFont(self):
1871 win = self.mdi_area.activeSubWindow()
1872 ShrinkFont(win.view)
1873
1874 def EnlargeFont(self):
1875 win = self.mdi_area.activeSubWindow()
1876 EnlargeFont(win.view)
1877
1878 def EventMenu(self, events, reports_menu):
1879 branches_events = 0
1880 for event in events:
1881 event = event.split(":")[0]
1882 if event == "branches":
1883 branches_events += 1
1884 dbid = 0
1885 for event in events:
1886 dbid += 1
1887 event = event.split(":")[0]
1888 if event == "branches":
1889 label = "All branches" if branches_events == 1 else "All branches " + "(id=" + dbid + ")"
1890 reports_menu.addAction(CreateAction(label, "Create a new window displaying branch events", lambda x=dbid: self.NewBranchView(x), self))
1891
1892 def TableMenu(self, tables, menu):
1893 table_menu = menu.addMenu("&Tables")
1894 for table in tables:
1895 table_menu.addAction(CreateAction(table, "Create a new window containing a table view", lambda t=table: self.NewTableView(t), self))
1896
1897 def NewCallGraph(self):
1898 CallGraphWindow(self.glb, self)
1899
1900 def NewBranchView(self, event_id):
1901 BranchWindow(self.glb, event_id, "", "", self)
1902
1903 def NewTableView(self, table_name):
1904 TableWindow(self.glb, table_name, self)
1905
1906# XED Disassembler
1907
1908class xed_state_t(Structure):
1909
1910 _fields_ = [
1911 ("mode", c_int),
1912 ("width", c_int)
1913 ]
1914
1915class XEDInstruction():
1916
1917 def __init__(self, libxed):
1918 # Current xed_decoded_inst_t structure is 192 bytes. Use 512 to allow for future expansion
1919 xedd_t = c_byte * 512
1920 self.xedd = xedd_t()
1921 self.xedp = addressof(self.xedd)
1922 libxed.xed_decoded_inst_zero(self.xedp)
1923 self.state = xed_state_t()
1924 self.statep = addressof(self.state)
1925 # Buffer for disassembled instruction text
1926 self.buffer = create_string_buffer(256)
1927 self.bufferp = addressof(self.buffer)
1928
1929class LibXED():
1930
1931 def __init__(self):
1932 self.libxed = CDLL("libxed.so")
1933
1934 self.xed_tables_init = self.libxed.xed_tables_init
1935 self.xed_tables_init.restype = None
1936 self.xed_tables_init.argtypes = []
1937
1938 self.xed_decoded_inst_zero = self.libxed.xed_decoded_inst_zero
1939 self.xed_decoded_inst_zero.restype = None
1940 self.xed_decoded_inst_zero.argtypes = [ c_void_p ]
1941
1942 self.xed_operand_values_set_mode = self.libxed.xed_operand_values_set_mode
1943 self.xed_operand_values_set_mode.restype = None
1944 self.xed_operand_values_set_mode.argtypes = [ c_void_p, c_void_p ]
1945
1946 self.xed_decoded_inst_zero_keep_mode = self.libxed.xed_decoded_inst_zero_keep_mode
1947 self.xed_decoded_inst_zero_keep_mode.restype = None
1948 self.xed_decoded_inst_zero_keep_mode.argtypes = [ c_void_p ]
1949
1950 self.xed_decode = self.libxed.xed_decode
1951 self.xed_decode.restype = c_int
1952 self.xed_decode.argtypes = [ c_void_p, c_void_p, c_uint ]
1953
1954 self.xed_format_context = self.libxed.xed_format_context
1955 self.xed_format_context.restype = c_uint
1956 self.xed_format_context.argtypes = [ c_int, c_void_p, c_void_p, c_int, c_ulonglong, c_void_p, c_void_p ]
1957
1958 self.xed_tables_init()
1959
1960 def Instruction(self):
1961 return XEDInstruction(self)
1962
1963 def SetMode(self, inst, mode):
1964 if mode:
1965 inst.state.mode = 4 # 32-bit
1966 inst.state.width = 4 # 4 bytes
1967 else:
1968 inst.state.mode = 1 # 64-bit
1969 inst.state.width = 8 # 8 bytes
1970 self.xed_operand_values_set_mode(inst.xedp, inst.statep)
1971
1972 def DisassembleOne(self, inst, bytes_ptr, bytes_cnt, ip):
1973 self.xed_decoded_inst_zero_keep_mode(inst.xedp)
1974 err = self.xed_decode(inst.xedp, bytes_ptr, bytes_cnt)
1975 if err:
1976 return 0, ""
1977 # Use AT&T mode (2), alternative is Intel (3)
1978 ok = self.xed_format_context(2, inst.xedp, inst.bufferp, sizeof(inst.buffer), ip, 0, 0)
1979 if not ok:
1980 return 0, ""
1981 # Return instruction length and the disassembled instruction text
1982 # For now, assume the length is in byte 166
1983 return inst.xedd[166], inst.buffer.value
1984
1985def TryOpen(file_name):
1986 try:
1987 return open(file_name, "rb")
1988 except:
1989 return None
1990
1991def Is64Bit(f):
1992 result = sizeof(c_void_p)
1993 # ELF support only
1994 pos = f.tell()
1995 f.seek(0)
1996 header = f.read(7)
1997 f.seek(pos)
1998 magic = header[0:4]
1999 eclass = ord(header[4])
2000 encoding = ord(header[5])
2001 version = ord(header[6])
2002 if magic == chr(127) + "ELF" and eclass > 0 and eclass < 3 and encoding > 0 and encoding < 3 and version == 1:
2003 result = True if eclass == 2 else False
2004 return result
2005
2006# Global data
2007
2008class Glb():
2009
2010 def __init__(self, dbref, db, dbname):
2011 self.dbref = dbref
2012 self.db = db
2013 self.dbname = dbname
2014 self.home_dir = os.path.expanduser("~")
2015 self.buildid_dir = os.getenv("PERF_BUILDID_DIR")
2016 if self.buildid_dir:
2017 self.buildid_dir += "/.build-id/"
2018 else:
2019 self.buildid_dir = self.home_dir + "/.debug/.build-id/"
2020 self.app = None
2021 self.mainwindow = None
2022 self.instances_to_shutdown_on_exit = weakref.WeakSet()
2023 try:
2024 self.disassembler = LibXED()
2025 self.have_disassembler = True
2026 except:
2027 self.have_disassembler = False
2028
2029 def FileFromBuildId(self, build_id):
2030 file_name = self.buildid_dir + build_id[0:2] + "/" + build_id[2:] + "/elf"
2031 return TryOpen(file_name)
2032
2033 def FileFromNamesAndBuildId(self, short_name, long_name, build_id):
2034 # Assume current machine i.e. no support for virtualization
2035 if short_name[0:7] == "[kernel" and os.path.basename(long_name) == "kcore":
2036 file_name = os.getenv("PERF_KCORE")
2037 f = TryOpen(file_name) if file_name else None
2038 if f:
2039 return f
2040 # For now, no special handling if long_name is /proc/kcore
2041 f = TryOpen(long_name)
2042 if f:
2043 return f
2044 f = self.FileFromBuildId(build_id)
2045 if f:
2046 return f
2047 return None
2048
2049 def AddInstanceToShutdownOnExit(self, instance):
2050 self.instances_to_shutdown_on_exit.add(instance)
2051
2052 # Shutdown any background processes or threads
2053 def ShutdownInstances(self):
2054 for x in self.instances_to_shutdown_on_exit:
2055 try:
2056 x.Shutdown()
2057 except:
2058 pass
2059
2060# Database reference
2061
2062class DBRef():
2063
2064 def __init__(self, is_sqlite3, dbname):
2065 self.is_sqlite3 = is_sqlite3
2066 self.dbname = dbname
2067
2068 def Open(self, connection_name):
2069 dbname = self.dbname
2070 if self.is_sqlite3:
2071 db = QSqlDatabase.addDatabase("QSQLITE", connection_name)
2072 else:
2073 db = QSqlDatabase.addDatabase("QPSQL", connection_name)
2074 opts = dbname.split()
2075 for opt in opts:
2076 if "=" in opt:
2077 opt = opt.split("=")
2078 if opt[0] == "hostname":
2079 db.setHostName(opt[1])
2080 elif opt[0] == "port":
2081 db.setPort(int(opt[1]))
2082 elif opt[0] == "username":
2083 db.setUserName(opt[1])
2084 elif opt[0] == "password":
2085 db.setPassword(opt[1])
2086 elif opt[0] == "dbname":
2087 dbname = opt[1]
2088 else:
2089 dbname = opt
2090
2091 db.setDatabaseName(dbname)
2092 if not db.open():
2093 raise Exception("Failed to open database " + dbname + " error: " + db.lastError().text())
2094 return db, dbname
2095
2096# Main
2097
2098def Main():
2099 if (len(sys.argv) < 2):
2100 print >> sys.stderr, "Usage is: exported-sql-viewer.py <database name>"
2101 raise Exception("Too few arguments")
2102
2103 dbname = sys.argv[1]
2104
2105 is_sqlite3 = False
2106 try:
2107 f = open(dbname)
2108 if f.read(15) == "SQLite format 3":
2109 is_sqlite3 = True
2110 f.close()
2111 except:
2112 pass
2113
2114 dbref = DBRef(is_sqlite3, dbname)
2115 db, dbname = dbref.Open("main")
2116 glb = Glb(dbref, db, dbname)
2117 app = QApplication(sys.argv)
2118 glb.app = app
2119 mainwindow = MainWindow(glb)
2120 glb.mainwindow = mainwindow
2121 mainwindow.show()
2122 err = app.exec_()
2123 glb.ShutdownInstances()
2124 db.close()
2125 sys.exit(err)
2126
2127if __name__ == "__main__":
2128 Main()
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build
index c3b0afd67760..304313073242 100644
--- a/tools/perf/trace/beauty/Build
+++ b/tools/perf/trace/beauty/Build
@@ -5,6 +5,7 @@ ifeq ($(SRCARCH),$(filter $(SRCARCH),x86))
5libperf-y += ioctl.o 5libperf-y += ioctl.o
6endif 6endif
7libperf-y += kcmp.o 7libperf-y += kcmp.o
8libperf-y += mount_flags.o
8libperf-y += pkey_alloc.o 9libperf-y += pkey_alloc.o
9libperf-y += prctl.o 10libperf-y += prctl.o
10libperf-y += sockaddr.o 11libperf-y += sockaddr.o
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index 2570152d3909..039c29039b2c 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -24,6 +24,7 @@ struct strarray {
24} 24}
25 25
26size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val); 26size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val);
27size_t strarray__scnprintf_flags(struct strarray *sa, char *bf, size_t size, unsigned long flags);
27 28
28struct trace; 29struct trace;
29struct thread; 30struct thread;
@@ -122,6 +123,12 @@ size_t syscall_arg__scnprintf_kcmp_type(char *bf, size_t size, struct syscall_ar
122size_t syscall_arg__scnprintf_kcmp_idx(char *bf, size_t size, struct syscall_arg *arg); 123size_t syscall_arg__scnprintf_kcmp_idx(char *bf, size_t size, struct syscall_arg *arg);
123#define SCA_KCMP_IDX syscall_arg__scnprintf_kcmp_idx 124#define SCA_KCMP_IDX syscall_arg__scnprintf_kcmp_idx
124 125
126unsigned long syscall_arg__mask_val_mount_flags(struct syscall_arg *arg, unsigned long flags);
127#define SCAMV_MOUNT_FLAGS syscall_arg__mask_val_mount_flags
128
129size_t syscall_arg__scnprintf_mount_flags(char *bf, size_t size, struct syscall_arg *arg);
130#define SCA_MOUNT_FLAGS syscall_arg__scnprintf_mount_flags
131
125size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg); 132size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg);
126#define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights 133#define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights
127 134
diff --git a/tools/perf/trace/beauty/clone.c b/tools/perf/trace/beauty/clone.c
index d64d049ab991..010406500c30 100644
--- a/tools/perf/trace/beauty/clone.c
+++ b/tools/perf/trace/beauty/clone.c
@@ -1,9 +1,8 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/cone.c 3 * trace/beauty/cone.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
diff --git a/tools/perf/trace/beauty/drm_ioctl.sh b/tools/perf/trace/beauty/drm_ioctl.sh
index 9d3816815e60..9aa94fd523a9 100755
--- a/tools/perf/trace/beauty/drm_ioctl.sh
+++ b/tools/perf/trace/beauty/drm_ioctl.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/drm/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/drm/
4 5
diff --git a/tools/perf/trace/beauty/eventfd.c b/tools/perf/trace/beauty/eventfd.c
index 5d6a477a6400..db5b9b492113 100644
--- a/tools/perf/trace/beauty/eventfd.c
+++ b/tools/perf/trace/beauty/eventfd.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#ifndef EFD_SEMAPHORE 2#ifndef EFD_SEMAPHORE
3#define EFD_SEMAPHORE 1 3#define EFD_SEMAPHORE 1
4#endif 4#endif
diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
index 9e8900c13cb1..e6de31674e24 100644
--- a/tools/perf/trace/beauty/fcntl.c
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -1,9 +1,8 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/fcntl.c 3 * trace/beauty/fcntl.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
diff --git a/tools/perf/trace/beauty/flock.c b/tools/perf/trace/beauty/flock.c
index c4ff6ad30b06..cf02ae5f0ba6 100644
--- a/tools/perf/trace/beauty/flock.c
+++ b/tools/perf/trace/beauty/flock.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2 2
3#include "trace/beauty/beauty.h" 3#include "trace/beauty/beauty.h"
4#include <linux/kernel.h> 4#include <linux/kernel.h>
diff --git a/tools/perf/trace/beauty/futex_op.c b/tools/perf/trace/beauty/futex_op.c
index 61850fbc85ff..1136bde56406 100644
--- a/tools/perf/trace/beauty/futex_op.c
+++ b/tools/perf/trace/beauty/futex_op.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <linux/futex.h> 2#include <linux/futex.h>
3 3
4#ifndef FUTEX_WAIT_BITSET 4#ifndef FUTEX_WAIT_BITSET
diff --git a/tools/perf/trace/beauty/futex_val3.c b/tools/perf/trace/beauty/futex_val3.c
index 26f6b3253511..138b7d588a70 100644
--- a/tools/perf/trace/beauty/futex_val3.c
+++ b/tools/perf/trace/beauty/futex_val3.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <linux/futex.h> 2#include <linux/futex.h>
3 3
4#ifndef FUTEX_BITSET_MATCH_ANY 4#ifndef FUTEX_BITSET_MATCH_ANY
diff --git a/tools/perf/trace/beauty/ioctl.c b/tools/perf/trace/beauty/ioctl.c
index 1be3b4cf0827..5d2a7fd8d407 100644
--- a/tools/perf/trace/beauty/ioctl.c
+++ b/tools/perf/trace/beauty/ioctl.c
@@ -1,9 +1,8 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/ioctl.c 3 * trace/beauty/ioctl.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
diff --git a/tools/perf/trace/beauty/kcmp.c b/tools/perf/trace/beauty/kcmp.c
index f62040eb9d5c..b276a274f203 100644
--- a/tools/perf/trace/beauty/kcmp.c
+++ b/tools/perf/trace/beauty/kcmp.c
@@ -1,9 +1,8 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/kcmp.c 3 * trace/beauty/kcmp.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
diff --git a/tools/perf/trace/beauty/kcmp_type.sh b/tools/perf/trace/beauty/kcmp_type.sh
index a3c304caa336..df8b17486d57 100755
--- a/tools/perf/trace/beauty/kcmp_type.sh
+++ b/tools/perf/trace/beauty/kcmp_type.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
4 5
diff --git a/tools/perf/trace/beauty/kvm_ioctl.sh b/tools/perf/trace/beauty/kvm_ioctl.sh
index c4699fd46bb6..4ce54f5bf756 100755
--- a/tools/perf/trace/beauty/kvm_ioctl.sh
+++ b/tools/perf/trace/beauty/kvm_ioctl.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
4 5
diff --git a/tools/perf/trace/beauty/madvise_behavior.sh b/tools/perf/trace/beauty/madvise_behavior.sh
index 431639eb4d29..4527d290cdfc 100755
--- a/tools/perf/trace/beauty/madvise_behavior.sh
+++ b/tools/perf/trace/beauty/madvise_behavior.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/
4 5
diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c
index 9f68077b241b..c534bd96ef5c 100644
--- a/tools/perf/trace/beauty/mmap.c
+++ b/tools/perf/trace/beauty/mmap.c
@@ -1,5 +1,6 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <uapi/linux/mman.h> 2#include <uapi/linux/mman.h>
3#include <linux/log2.h>
3 4
4static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, 5static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
5 struct syscall_arg *arg) 6 struct syscall_arg *arg)
@@ -30,50 +31,23 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
30 31
31#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot 32#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
32 33
34static size_t mmap__scnprintf_flags(unsigned long flags, char *bf, size_t size)
35{
36#include "trace/beauty/generated/mmap_flags_array.c"
37 static DEFINE_STRARRAY(mmap_flags);
38
39 return strarray__scnprintf_flags(&strarray__mmap_flags, bf, size, flags);
40}
41
33static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, 42static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
34 struct syscall_arg *arg) 43 struct syscall_arg *arg)
35{ 44{
36 int printed = 0, flags = arg->val; 45 unsigned long flags = arg->val;
37 46
38 if (flags & MAP_ANONYMOUS) 47 if (flags & MAP_ANONYMOUS)
39 arg->mask |= (1 << 4) | (1 << 5); /* Mask 4th ('fd') and 5th ('offset') args, ignored */ 48 arg->mask |= (1 << 4) | (1 << 5); /* Mask 4th ('fd') and 5th ('offset') args, ignored */
40 49
41#define P_MMAP_FLAG(n) \ 50 return mmap__scnprintf_flags(flags, bf, size);
42 if (flags & MAP_##n) { \
43 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
44 flags &= ~MAP_##n; \
45 }
46
47 P_MMAP_FLAG(SHARED);
48 P_MMAP_FLAG(PRIVATE);
49#ifdef MAP_32BIT
50 P_MMAP_FLAG(32BIT);
51#endif
52 P_MMAP_FLAG(ANONYMOUS);
53 P_MMAP_FLAG(DENYWRITE);
54 P_MMAP_FLAG(EXECUTABLE);
55 P_MMAP_FLAG(FILE);
56 P_MMAP_FLAG(FIXED);
57#ifdef MAP_FIXED_NOREPLACE
58 P_MMAP_FLAG(FIXED_NOREPLACE);
59#endif
60 P_MMAP_FLAG(GROWSDOWN);
61 P_MMAP_FLAG(HUGETLB);
62 P_MMAP_FLAG(LOCKED);
63 P_MMAP_FLAG(NONBLOCK);
64 P_MMAP_FLAG(NORESERVE);
65 P_MMAP_FLAG(POPULATE);
66 P_MMAP_FLAG(STACK);
67 P_MMAP_FLAG(UNINITIALIZED);
68#ifdef MAP_SYNC
69 P_MMAP_FLAG(SYNC);
70#endif
71#undef P_MMAP_FLAG
72
73 if (flags)
74 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
75
76 return printed;
77} 51}
78 52
79#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags 53#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
diff --git a/tools/perf/trace/beauty/mmap_flags.sh b/tools/perf/trace/beauty/mmap_flags.sh
new file mode 100755
index 000000000000..22c3fdca8975
--- /dev/null
+++ b/tools/perf/trace/beauty/mmap_flags.sh
@@ -0,0 +1,32 @@
1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
3
4if [ $# -ne 2 ] ; then
5 [ $# -eq 1 ] && hostarch=$1 || hostarch=`uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/`
6 header_dir=tools/include/uapi/asm-generic
7 arch_header_dir=tools/arch/${hostarch}/include/uapi/asm
8else
9 header_dir=$1
10 arch_header_dir=$2
11fi
12
13arch_mman=${arch_header_dir}/mman.h
14
15# those in egrep -vw are flags, we want just the bits
16
17printf "static const char *mmap_flags[] = {\n"
18regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MAP_([[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*.*'
19egrep -q $regex ${arch_mman} && \
20(egrep $regex ${arch_mman} | \
21 sed -r "s/$regex/\2 \1/g" | \
22 xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n")
23egrep -q '#[[:space:]]*include[[:space:]]+<uapi/asm-generic/mman.*' ${arch_mman} &&
24(egrep $regex ${header_dir}/mman-common.h | \
25 egrep -vw 'MAP_(UNINITIALIZED|TYPE|SHARED_VALIDATE)' | \
26 sed -r "s/$regex/\2 \1/g" | \
27 xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n")
28egrep -q '#[[:space:]]*include[[:space:]]+<uapi/asm-generic/mman.h>.*' ${arch_mman} &&
29(egrep $regex ${header_dir}/mman.h | \
30 sed -r "s/$regex/\2 \1/g" | \
31 xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n")
32printf "};\n"
diff --git a/tools/perf/trace/beauty/mode_t.c b/tools/perf/trace/beauty/mode_t.c
index d929ad7dd97b..6879d36d3004 100644
--- a/tools/perf/trace/beauty/mode_t.c
+++ b/tools/perf/trace/beauty/mode_t.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <sys/types.h> 2#include <sys/types.h>
3#include <sys/stat.h> 3#include <sys/stat.h>
4#include <unistd.h> 4#include <unistd.h>
diff --git a/tools/perf/trace/beauty/mount_flags.c b/tools/perf/trace/beauty/mount_flags.c
new file mode 100644
index 000000000000..712935c6620a
--- /dev/null
+++ b/tools/perf/trace/beauty/mount_flags.c
@@ -0,0 +1,43 @@
1// SPDX-License-Identifier: LGPL-2.1
2/*
3 * trace/beauty/mount_flags.c
4 *
5 * Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
6 */
7
8#include "trace/beauty/beauty.h"
9#include <linux/compiler.h>
10#include <linux/kernel.h>
11#include <linux/log2.h>
12#include <sys/mount.h>
13
14static size_t mount__scnprintf_flags(unsigned long flags, char *bf, size_t size)
15{
16#include "trace/beauty/generated/mount_flags_array.c"
17 static DEFINE_STRARRAY(mount_flags);
18
19 return strarray__scnprintf_flags(&strarray__mount_flags, bf, size, flags);
20}
21
22unsigned long syscall_arg__mask_val_mount_flags(struct syscall_arg *arg __maybe_unused, unsigned long flags)
23{
24 // do_mount in fs/namespace.c:
25 /*
26 * Pre-0.97 versions of mount() didn't have a flags word. When the
27 * flags word was introduced its top half was required to have the
28 * magic value 0xC0ED, and this remained so until 2.4.0-test9.
29 * Therefore, if this magic number is present, it carries no
30 * information and must be discarded.
31 */
32 if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
33 flags &= ~MS_MGC_MSK;
34
35 return flags;
36}
37
38size_t syscall_arg__scnprintf_mount_flags(char *bf, size_t size, struct syscall_arg *arg)
39{
40 unsigned long flags = arg->val;
41
42 return mount__scnprintf_flags(flags, bf, size);
43}
diff --git a/tools/perf/trace/beauty/mount_flags.sh b/tools/perf/trace/beauty/mount_flags.sh
new file mode 100755
index 000000000000..45547573a1db
--- /dev/null
+++ b/tools/perf/trace/beauty/mount_flags.sh
@@ -0,0 +1,15 @@
1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
3
4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
5
6printf "static const char *mount_flags[] = {\n"
7regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MS_([[:alnum:]_]+)[[:space:]]+([[:digit:]]+)[[:space:]]*.*'
8egrep $regex ${header_dir}/fs.h | egrep -v '(MSK|VERBOSE|MGC_VAL)\>' | \
9 sed -r "s/$regex/\2 \2 \1/g" | sort -n | \
10 xargs printf "\t[%s ? (ilog2(%s) + 1) : 0] = \"%s\",\n"
11regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MS_([[:alnum:]_]+)[[:space:]]+\(1<<([[:digit:]]+)\)[[:space:]]*.*'
12egrep $regex ${header_dir}/fs.h | \
13 sed -r "s/$regex/\2 \1/g" | \
14 xargs printf "\t[%s + 1] = \"%s\",\n"
15printf "};\n"
diff --git a/tools/perf/trace/beauty/msg_flags.c b/tools/perf/trace/beauty/msg_flags.c
index c064d6aae659..1b9d6306d274 100644
--- a/tools/perf/trace/beauty/msg_flags.c
+++ b/tools/perf/trace/beauty/msg_flags.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <sys/types.h> 2#include <sys/types.h>
3#include <sys/socket.h> 3#include <sys/socket.h>
4 4
diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
index 6aec6178a99d..cc673fec9184 100644
--- a/tools/perf/trace/beauty/open_flags.c
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <sys/types.h> 2#include <sys/types.h>
3#include <sys/stat.h> 3#include <sys/stat.h>
4#include <fcntl.h> 4#include <fcntl.h>
diff --git a/tools/perf/trace/beauty/perf_event_open.c b/tools/perf/trace/beauty/perf_event_open.c
index 2bafd7c995ff..981185c1974b 100644
--- a/tools/perf/trace/beauty/perf_event_open.c
+++ b/tools/perf/trace/beauty/perf_event_open.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#ifndef PERF_FLAG_FD_NO_GROUP 2#ifndef PERF_FLAG_FD_NO_GROUP
3# define PERF_FLAG_FD_NO_GROUP (1UL << 0) 3# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
4#endif 4#endif
diff --git a/tools/perf/trace/beauty/perf_ioctl.sh b/tools/perf/trace/beauty/perf_ioctl.sh
index 6492c74df928..9aabd9743ef6 100755
--- a/tools/perf/trace/beauty/perf_ioctl.sh
+++ b/tools/perf/trace/beauty/perf_ioctl.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
4 5
diff --git a/tools/perf/trace/beauty/pid.c b/tools/perf/trace/beauty/pid.c
index 0313df342830..1a6acc46807b 100644
--- a/tools/perf/trace/beauty/pid.c
+++ b/tools/perf/trace/beauty/pid.c
@@ -1,4 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2
2size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg) 3size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
3{ 4{
4 int pid = arg->val; 5 int pid = arg->val;
diff --git a/tools/perf/trace/beauty/pkey_alloc.c b/tools/perf/trace/beauty/pkey_alloc.c
index 2ba784a3734a..1b8ed4cac815 100644
--- a/tools/perf/trace/beauty/pkey_alloc.c
+++ b/tools/perf/trace/beauty/pkey_alloc.c
@@ -1,40 +1,36 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/pkey_alloc.c 3 * trace/beauty/pkey_alloc.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
10#include <linux/kernel.h> 9#include <linux/kernel.h>
11#include <linux/log2.h> 10#include <linux/log2.h>
12 11
13static size_t pkey_alloc__scnprintf_access_rights(int access_rights, char *bf, size_t size) 12size_t strarray__scnprintf_flags(struct strarray *sa, char *bf, size_t size, unsigned long flags)
14{ 13{
15 int i, printed = 0; 14 int i, printed = 0;
16 15
17#include "trace/beauty/generated/pkey_alloc_access_rights_array.c" 16 if (flags == 0) {
18 static DEFINE_STRARRAY(pkey_alloc_access_rights); 17 const char *s = sa->entries[0];
19
20 if (access_rights == 0) {
21 const char *s = strarray__pkey_alloc_access_rights.entries[0];
22 if (s) 18 if (s)
23 return scnprintf(bf, size, "%s", s); 19 return scnprintf(bf, size, "%s", s);
24 return scnprintf(bf, size, "%d", 0); 20 return scnprintf(bf, size, "%d", 0);
25 } 21 }
26 22
27 for (i = 1; i < strarray__pkey_alloc_access_rights.nr_entries; ++i) { 23 for (i = 1; i < sa->nr_entries; ++i) {
28 int bit = 1 << (i - 1); 24 unsigned long bit = 1UL << (i - 1);
29 25
30 if (!(access_rights & bit)) 26 if (!(flags & bit))
31 continue; 27 continue;
32 28
33 if (printed != 0) 29 if (printed != 0)
34 printed += scnprintf(bf + printed, size - printed, "|"); 30 printed += scnprintf(bf + printed, size - printed, "|");
35 31
36 if (strarray__pkey_alloc_access_rights.entries[i] != NULL) 32 if (sa->entries[i] != NULL)
37 printed += scnprintf(bf + printed, size - printed, "%s", strarray__pkey_alloc_access_rights.entries[i]); 33 printed += scnprintf(bf + printed, size - printed, "%s", sa->entries[i]);
38 else 34 else
39 printed += scnprintf(bf + printed, size - printed, "0x%#", bit); 35 printed += scnprintf(bf + printed, size - printed, "0x%#", bit);
40 } 36 }
@@ -42,6 +38,14 @@ static size_t pkey_alloc__scnprintf_access_rights(int access_rights, char *bf, s
42 return printed; 38 return printed;
43} 39}
44 40
41static size_t pkey_alloc__scnprintf_access_rights(int access_rights, char *bf, size_t size)
42{
43#include "trace/beauty/generated/pkey_alloc_access_rights_array.c"
44 static DEFINE_STRARRAY(pkey_alloc_access_rights);
45
46 return strarray__scnprintf_flags(&strarray__pkey_alloc_access_rights, bf, size, access_rights);
47}
48
45size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg) 49size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg)
46{ 50{
47 unsigned long cmd = arg->val; 51 unsigned long cmd = arg->val;
diff --git a/tools/perf/trace/beauty/pkey_alloc_access_rights.sh b/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
index e0a51aeb20b2..f8f1b560cf8a 100755
--- a/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
+++ b/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/
4 5
diff --git a/tools/perf/trace/beauty/prctl.c b/tools/perf/trace/beauty/prctl.c
index 246130dad6c4..be7a5d395975 100644
--- a/tools/perf/trace/beauty/prctl.c
+++ b/tools/perf/trace/beauty/prctl.c
@@ -1,9 +1,8 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/prctl.c 3 * trace/beauty/prctl.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
diff --git a/tools/perf/trace/beauty/prctl_option.sh b/tools/perf/trace/beauty/prctl_option.sh
index f24722146ebe..d32f8f1124af 100755
--- a/tools/perf/trace/beauty/prctl_option.sh
+++ b/tools/perf/trace/beauty/prctl_option.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
4 5
diff --git a/tools/perf/trace/beauty/sched_policy.c b/tools/perf/trace/beauty/sched_policy.c
index ba5096ae76b6..48f2b5c9aa3e 100644
--- a/tools/perf/trace/beauty/sched_policy.c
+++ b/tools/perf/trace/beauty/sched_policy.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <sched.h> 2#include <sched.h>
3 3
4/* 4/*
diff --git a/tools/perf/trace/beauty/seccomp.c b/tools/perf/trace/beauty/seccomp.c
index b7097fd5fed9..e36156b19c70 100644
--- a/tools/perf/trace/beauty/seccomp.c
+++ b/tools/perf/trace/beauty/seccomp.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#ifndef SECCOMP_SET_MODE_STRICT 2#ifndef SECCOMP_SET_MODE_STRICT
3#define SECCOMP_SET_MODE_STRICT 0 3#define SECCOMP_SET_MODE_STRICT 0
4#endif 4#endif
diff --git a/tools/perf/trace/beauty/signum.c b/tools/perf/trace/beauty/signum.c
index bde18a53f090..587fec545b8a 100644
--- a/tools/perf/trace/beauty/signum.c
+++ b/tools/perf/trace/beauty/signum.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <signal.h> 2#include <signal.h>
3 3
4static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg) 4static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
diff --git a/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh b/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh
index eb511bb5fbd3..e0803b957593 100755
--- a/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh
+++ b/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/
4 5
diff --git a/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh b/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
index 6818392968b2..7a464a7bf913 100755
--- a/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
+++ b/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/
4 5
diff --git a/tools/perf/trace/beauty/sockaddr.c b/tools/perf/trace/beauty/sockaddr.c
index 71a79f72d9d9..9410ad230f10 100644
--- a/tools/perf/trace/beauty/sockaddr.c
+++ b/tools/perf/trace/beauty/sockaddr.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2// Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 2// Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 3
4#include "trace/beauty/beauty.h" 4#include "trace/beauty/beauty.h"
diff --git a/tools/perf/trace/beauty/socket.c b/tools/perf/trace/beauty/socket.c
index 65227269384b..d971a2596417 100644
--- a/tools/perf/trace/beauty/socket.c
+++ b/tools/perf/trace/beauty/socket.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2/* 2/*
3 * trace/beauty/socket.c 3 * trace/beauty/socket.c
4 * 4 *
diff --git a/tools/perf/trace/beauty/socket_ipproto.sh b/tools/perf/trace/beauty/socket_ipproto.sh
index a3cc24633bec..de0f2f29017f 100755
--- a/tools/perf/trace/beauty/socket_ipproto.sh
+++ b/tools/perf/trace/beauty/socket_ipproto.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
4 5
diff --git a/tools/perf/trace/beauty/socket_type.c b/tools/perf/trace/beauty/socket_type.c
index bca26aef4a77..a63a9a332aa0 100644
--- a/tools/perf/trace/beauty/socket_type.c
+++ b/tools/perf/trace/beauty/socket_type.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <sys/types.h> 2#include <sys/types.h>
3#include <sys/socket.h> 3#include <sys/socket.h>
4 4
diff --git a/tools/perf/trace/beauty/statx.c b/tools/perf/trace/beauty/statx.c
index 5643b692af4c..630f2760dd66 100644
--- a/tools/perf/trace/beauty/statx.c
+++ b/tools/perf/trace/beauty/statx.c
@@ -1,9 +1,8 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/statx.c 3 * trace/beauty/statx.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
diff --git a/tools/perf/trace/beauty/vhost_virtio_ioctl.sh b/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
index 0f6a5197d0be..439773daaf77 100755
--- a/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
+++ b/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
4 5
diff --git a/tools/perf/trace/beauty/waitid_options.c b/tools/perf/trace/beauty/waitid_options.c
index 8465281a093d..42ff58ad613b 100644
--- a/tools/perf/trace/beauty/waitid_options.c
+++ b/tools/perf/trace/beauty/waitid_options.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <sys/types.h> 2#include <sys/types.h>
3#include <sys/wait.h> 3#include <sys/wait.h>
4 4
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 28cd6a17491b..6936daf89ddd 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -139,6 +139,7 @@ static int arch__associate_ins_ops(struct arch* arch, const char *name, struct i
139#include "arch/x86/annotate/instructions.c" 139#include "arch/x86/annotate/instructions.c"
140#include "arch/powerpc/annotate/instructions.c" 140#include "arch/powerpc/annotate/instructions.c"
141#include "arch/s390/annotate/instructions.c" 141#include "arch/s390/annotate/instructions.c"
142#include "arch/sparc/annotate/instructions.c"
142 143
143static struct arch architectures[] = { 144static struct arch architectures[] = {
144 { 145 {
@@ -170,6 +171,13 @@ static struct arch architectures[] = {
170 .comment_char = '#', 171 .comment_char = '#',
171 }, 172 },
172 }, 173 },
174 {
175 .name = "sparc",
176 .init = sparc__annotate_init,
177 .objdump = {
178 .comment_char = '#',
179 },
180 },
173}; 181};
174 182
175static void ins__delete(struct ins_operands *ops) 183static void ins__delete(struct ins_operands *ops)
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index c4617bcfd521..72d5ba2479bf 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -962,16 +962,23 @@ s64 perf_event__process_auxtrace(struct perf_session *session,
962#define PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ 64 962#define PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ 64
963#define PERF_ITRACE_MAX_LAST_BRANCH_SZ 1024 963#define PERF_ITRACE_MAX_LAST_BRANCH_SZ 1024
964 964
965void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts) 965void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts,
966 bool no_sample)
966{ 967{
967 synth_opts->instructions = true;
968 synth_opts->branches = true; 968 synth_opts->branches = true;
969 synth_opts->transactions = true; 969 synth_opts->transactions = true;
970 synth_opts->ptwrites = true; 970 synth_opts->ptwrites = true;
971 synth_opts->pwr_events = true; 971 synth_opts->pwr_events = true;
972 synth_opts->errors = true; 972 synth_opts->errors = true;
973 synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE; 973 if (no_sample) {
974 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; 974 synth_opts->period_type = PERF_ITRACE_PERIOD_INSTRUCTIONS;
975 synth_opts->period = 1;
976 synth_opts->calls = true;
977 } else {
978 synth_opts->instructions = true;
979 synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE;
980 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
981 }
975 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ; 982 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
976 synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ; 983 synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ;
977 synth_opts->initial_skip = 0; 984 synth_opts->initial_skip = 0;
@@ -999,7 +1006,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
999 } 1006 }
1000 1007
1001 if (!str) { 1008 if (!str) {
1002 itrace_synth_opts__set_default(synth_opts); 1009 itrace_synth_opts__set_default(synth_opts, false);
1003 return 0; 1010 return 0;
1004 } 1011 }
1005 1012
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index d88f6e9eb461..8e50f96d4b23 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -58,6 +58,7 @@ enum itrace_period_type {
58/** 58/**
59 * struct itrace_synth_opts - AUX area tracing synthesis options. 59 * struct itrace_synth_opts - AUX area tracing synthesis options.
60 * @set: indicates whether or not options have been set 60 * @set: indicates whether or not options have been set
61 * @default_no_sample: Default to no sampling.
61 * @inject: indicates the event (not just the sample) must be fully synthesized 62 * @inject: indicates the event (not just the sample) must be fully synthesized
62 * because 'perf inject' will write it out 63 * because 'perf inject' will write it out
63 * @instructions: whether to synthesize 'instructions' events 64 * @instructions: whether to synthesize 'instructions' events
@@ -82,6 +83,7 @@ enum itrace_period_type {
82 */ 83 */
83struct itrace_synth_opts { 84struct itrace_synth_opts {
84 bool set; 85 bool set;
86 bool default_no_sample;
85 bool inject; 87 bool inject;
86 bool instructions; 88 bool instructions;
87 bool branches; 89 bool branches;
@@ -528,7 +530,8 @@ int perf_event__process_auxtrace_error(struct perf_session *session,
528 union perf_event *event); 530 union perf_event *event);
529int itrace_parse_synth_opts(const struct option *opt, const char *str, 531int itrace_parse_synth_opts(const struct option *opt, const char *str,
530 int unset); 532 int unset);
531void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts); 533void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts,
534 bool no_sample);
532 535
533size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp); 536size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp);
534void perf_session__auxtrace_error_inc(struct perf_session *session, 537void perf_session__auxtrace_error_inc(struct perf_session *session,
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 2ae640257fdb..73430b73570d 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -244,6 +244,27 @@ static void cs_etm__free(struct perf_session *session)
244 zfree(&aux); 244 zfree(&aux);
245} 245}
246 246
247static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address)
248{
249 struct machine *machine;
250
251 machine = etmq->etm->machine;
252
253 if (address >= etmq->etm->kernel_start) {
254 if (machine__is_host(machine))
255 return PERF_RECORD_MISC_KERNEL;
256 else
257 return PERF_RECORD_MISC_GUEST_KERNEL;
258 } else {
259 if (machine__is_host(machine))
260 return PERF_RECORD_MISC_USER;
261 else if (perf_guest)
262 return PERF_RECORD_MISC_GUEST_USER;
263 else
264 return PERF_RECORD_MISC_HYPERVISOR;
265 }
266}
267
247static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address, 268static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address,
248 size_t size, u8 *buffer) 269 size_t size, u8 *buffer)
249{ 270{
@@ -258,10 +279,7 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address,
258 return -1; 279 return -1;
259 280
260 machine = etmq->etm->machine; 281 machine = etmq->etm->machine;
261 if (address >= etmq->etm->kernel_start) 282 cpumode = cs_etm__cpu_mode(etmq, address);
262 cpumode = PERF_RECORD_MISC_KERNEL;
263 else
264 cpumode = PERF_RECORD_MISC_USER;
265 283
266 thread = etmq->thread; 284 thread = etmq->thread;
267 if (!thread) { 285 if (!thread) {
@@ -653,7 +671,7 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
653 struct perf_sample sample = {.ip = 0,}; 671 struct perf_sample sample = {.ip = 0,};
654 672
655 event->sample.header.type = PERF_RECORD_SAMPLE; 673 event->sample.header.type = PERF_RECORD_SAMPLE;
656 event->sample.header.misc = PERF_RECORD_MISC_USER; 674 event->sample.header.misc = cs_etm__cpu_mode(etmq, addr);
657 event->sample.header.size = sizeof(struct perf_event_header); 675 event->sample.header.size = sizeof(struct perf_event_header);
658 676
659 sample.ip = addr; 677 sample.ip = addr;
@@ -665,7 +683,7 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
665 sample.cpu = etmq->packet->cpu; 683 sample.cpu = etmq->packet->cpu;
666 sample.flags = 0; 684 sample.flags = 0;
667 sample.insn_len = 1; 685 sample.insn_len = 1;
668 sample.cpumode = event->header.misc; 686 sample.cpumode = event->sample.header.misc;
669 687
670 if (etm->synth_opts.last_branch) { 688 if (etm->synth_opts.last_branch) {
671 cs_etm__copy_last_branch_rb(etmq); 689 cs_etm__copy_last_branch_rb(etmq);
@@ -706,12 +724,15 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
706 u64 nr; 724 u64 nr;
707 struct branch_entry entries; 725 struct branch_entry entries;
708 } dummy_bs; 726 } dummy_bs;
727 u64 ip;
728
729 ip = cs_etm__last_executed_instr(etmq->prev_packet);
709 730
710 event->sample.header.type = PERF_RECORD_SAMPLE; 731 event->sample.header.type = PERF_RECORD_SAMPLE;
711 event->sample.header.misc = PERF_RECORD_MISC_USER; 732 event->sample.header.misc = cs_etm__cpu_mode(etmq, ip);
712 event->sample.header.size = sizeof(struct perf_event_header); 733 event->sample.header.size = sizeof(struct perf_event_header);
713 734
714 sample.ip = cs_etm__last_executed_instr(etmq->prev_packet); 735 sample.ip = ip;
715 sample.pid = etmq->pid; 736 sample.pid = etmq->pid;
716 sample.tid = etmq->tid; 737 sample.tid = etmq->tid;
717 sample.addr = cs_etm__first_executed_instr(etmq->packet); 738 sample.addr = cs_etm__first_executed_instr(etmq->packet);
@@ -720,7 +741,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
720 sample.period = 1; 741 sample.period = 1;
721 sample.cpu = etmq->packet->cpu; 742 sample.cpu = etmq->packet->cpu;
722 sample.flags = 0; 743 sample.flags = 0;
723 sample.cpumode = PERF_RECORD_MISC_USER; 744 sample.cpumode = event->sample.header.misc;
724 745
725 /* 746 /*
726 * perf report cannot handle events without a branch stack 747 * perf report cannot handle events without a branch stack
@@ -1432,7 +1453,8 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
1432 if (session->itrace_synth_opts && session->itrace_synth_opts->set) { 1453 if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
1433 etm->synth_opts = *session->itrace_synth_opts; 1454 etm->synth_opts = *session->itrace_synth_opts;
1434 } else { 1455 } else {
1435 itrace_synth_opts__set_default(&etm->synth_opts); 1456 itrace_synth_opts__set_default(&etm->synth_opts,
1457 session->itrace_synth_opts->default_no_sample);
1436 etm->synth_opts.callchain = false; 1458 etm->synth_opts.callchain = false;
1437 } 1459 }
1438 1460
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index 1f3ccc368530..d01b8355f4ca 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -63,6 +63,7 @@ struct perf_env {
63 struct numa_node *numa_nodes; 63 struct numa_node *numa_nodes;
64 struct memory_node *memory_nodes; 64 struct memory_node *memory_nodes;
65 unsigned long long memory_bsize; 65 unsigned long long memory_bsize;
66 u64 clockid_res_ns;
66}; 67};
67 68
68extern struct perf_env perf_env; 69extern struct perf_env perf_env;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index bc646185f8d9..e9c108a6b1c3 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -308,6 +308,7 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
308 event->fork.pid = tgid; 308 event->fork.pid = tgid;
309 event->fork.tid = pid; 309 event->fork.tid = pid;
310 event->fork.header.type = PERF_RECORD_FORK; 310 event->fork.header.type = PERF_RECORD_FORK;
311 event->fork.header.misc = PERF_RECORD_MISC_FORK_EXEC;
311 312
312 event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size); 313 event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size);
313 314
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index be440df29615..e88e6f9b1463 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -358,7 +358,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)
358 struct perf_evsel *pos; 358 struct perf_evsel *pos;
359 359
360 evlist__for_each_entry(evlist, pos) { 360 evlist__for_each_entry(evlist, pos) {
361 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 361 if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->fd)
362 continue; 362 continue;
363 perf_evsel__disable(pos); 363 perf_evsel__disable(pos);
364 } 364 }
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 29d7b97f66fb..6d187059a373 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -232,6 +232,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
232 evsel->leader = evsel; 232 evsel->leader = evsel;
233 evsel->unit = ""; 233 evsel->unit = "";
234 evsel->scale = 1.0; 234 evsel->scale = 1.0;
235 evsel->max_events = ULONG_MAX;
235 evsel->evlist = NULL; 236 evsel->evlist = NULL;
236 evsel->bpf_fd = -1; 237 evsel->bpf_fd = -1;
237 INIT_LIST_HEAD(&evsel->node); 238 INIT_LIST_HEAD(&evsel->node);
@@ -793,6 +794,9 @@ static void apply_config_terms(struct perf_evsel *evsel,
793 case PERF_EVSEL__CONFIG_TERM_MAX_STACK: 794 case PERF_EVSEL__CONFIG_TERM_MAX_STACK:
794 max_stack = term->val.max_stack; 795 max_stack = term->val.max_stack;
795 break; 796 break;
797 case PERF_EVSEL__CONFIG_TERM_MAX_EVENTS:
798 evsel->max_events = term->val.max_events;
799 break;
796 case PERF_EVSEL__CONFIG_TERM_INHERIT: 800 case PERF_EVSEL__CONFIG_TERM_INHERIT:
797 /* 801 /*
798 * attr->inherit should has already been set by 802 * attr->inherit should has already been set by
@@ -1203,16 +1207,27 @@ int perf_evsel__append_addr_filter(struct perf_evsel *evsel, const char *filter)
1203 1207
1204int perf_evsel__enable(struct perf_evsel *evsel) 1208int perf_evsel__enable(struct perf_evsel *evsel)
1205{ 1209{
1206 return perf_evsel__run_ioctl(evsel, 1210 int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0);
1207 PERF_EVENT_IOC_ENABLE, 1211
1208 0); 1212 if (!err)
1213 evsel->disabled = false;
1214
1215 return err;
1209} 1216}
1210 1217
1211int perf_evsel__disable(struct perf_evsel *evsel) 1218int perf_evsel__disable(struct perf_evsel *evsel)
1212{ 1219{
1213 return perf_evsel__run_ioctl(evsel, 1220 int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0);
1214 PERF_EVENT_IOC_DISABLE, 1221 /*
1215 0); 1222 * We mark it disabled here so that tools that disable a event can
1223 * ignore events after they disable it. I.e. the ring buffer may have
1224 * already a few more events queued up before the kernel got the stop
1225 * request.
1226 */
1227 if (!err)
1228 evsel->disabled = true;
1229
1230 return err;
1216} 1231}
1217 1232
1218int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 1233int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 4107c39f4a54..3147ca76c6fc 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -46,6 +46,7 @@ enum term_type {
46 PERF_EVSEL__CONFIG_TERM_STACK_USER, 46 PERF_EVSEL__CONFIG_TERM_STACK_USER,
47 PERF_EVSEL__CONFIG_TERM_INHERIT, 47 PERF_EVSEL__CONFIG_TERM_INHERIT,
48 PERF_EVSEL__CONFIG_TERM_MAX_STACK, 48 PERF_EVSEL__CONFIG_TERM_MAX_STACK,
49 PERF_EVSEL__CONFIG_TERM_MAX_EVENTS,
49 PERF_EVSEL__CONFIG_TERM_OVERWRITE, 50 PERF_EVSEL__CONFIG_TERM_OVERWRITE,
50 PERF_EVSEL__CONFIG_TERM_DRV_CFG, 51 PERF_EVSEL__CONFIG_TERM_DRV_CFG,
51 PERF_EVSEL__CONFIG_TERM_BRANCH, 52 PERF_EVSEL__CONFIG_TERM_BRANCH,
@@ -65,6 +66,7 @@ struct perf_evsel_config_term {
65 bool inherit; 66 bool inherit;
66 bool overwrite; 67 bool overwrite;
67 char *branch; 68 char *branch;
69 unsigned long max_events;
68 } val; 70 } val;
69 bool weak; 71 bool weak;
70}; 72};
@@ -99,6 +101,8 @@ struct perf_evsel {
99 struct perf_counts *prev_raw_counts; 101 struct perf_counts *prev_raw_counts;
100 int idx; 102 int idx;
101 u32 ids; 103 u32 ids;
104 unsigned long max_events;
105 unsigned long nr_events_printed;
102 char *name; 106 char *name;
103 double scale; 107 double scale;
104 const char *unit; 108 const char *unit;
@@ -119,6 +123,7 @@ struct perf_evsel {
119 bool snapshot; 123 bool snapshot;
120 bool supported; 124 bool supported;
121 bool needs_swap; 125 bool needs_swap;
126 bool disabled;
122 bool no_aux_samples; 127 bool no_aux_samples;
123 bool immediate; 128 bool immediate;
124 bool system_wide; 129 bool system_wide;
diff --git a/tools/perf/util/genelf.h b/tools/perf/util/genelf.h
index de322d51c7fe..b72440bf9a79 100644
--- a/tools/perf/util/genelf.h
+++ b/tools/perf/util/genelf.h
@@ -29,6 +29,12 @@ int jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_ent
29#elif defined(__powerpc__) 29#elif defined(__powerpc__)
30#define GEN_ELF_ARCH EM_PPC 30#define GEN_ELF_ARCH EM_PPC
31#define GEN_ELF_CLASS ELFCLASS32 31#define GEN_ELF_CLASS ELFCLASS32
32#elif defined(__sparc__) && defined(__arch64__)
33#define GEN_ELF_ARCH EM_SPARCV9
34#define GEN_ELF_CLASS ELFCLASS64
35#elif defined(__sparc__)
36#define GEN_ELF_ARCH EM_SPARC
37#define GEN_ELF_CLASS ELFCLASS32
32#else 38#else
33#error "unsupported architecture" 39#error "unsupported architecture"
34#endif 40#endif
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1ec1d9bc2d63..4fd45be95a43 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1034,6 +1034,13 @@ static int write_auxtrace(struct feat_fd *ff,
1034 return err; 1034 return err;
1035} 1035}
1036 1036
1037static int write_clockid(struct feat_fd *ff,
1038 struct perf_evlist *evlist __maybe_unused)
1039{
1040 return do_write(ff, &ff->ph->env.clockid_res_ns,
1041 sizeof(ff->ph->env.clockid_res_ns));
1042}
1043
1037static int cpu_cache_level__sort(const void *a, const void *b) 1044static int cpu_cache_level__sort(const void *a, const void *b)
1038{ 1045{
1039 struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a; 1046 struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
@@ -1508,6 +1515,12 @@ static void print_cpu_topology(struct feat_fd *ff, FILE *fp)
1508 fprintf(fp, "# Core ID and Socket ID information is not available\n"); 1515 fprintf(fp, "# Core ID and Socket ID information is not available\n");
1509} 1516}
1510 1517
1518static void print_clockid(struct feat_fd *ff, FILE *fp)
1519{
1520 fprintf(fp, "# clockid frequency: %"PRIu64" MHz\n",
1521 ff->ph->env.clockid_res_ns * 1000);
1522}
1523
1511static void free_event_desc(struct perf_evsel *events) 1524static void free_event_desc(struct perf_evsel *events)
1512{ 1525{
1513 struct perf_evsel *evsel; 1526 struct perf_evsel *evsel;
@@ -2531,6 +2544,15 @@ out:
2531 return ret; 2544 return ret;
2532} 2545}
2533 2546
2547static int process_clockid(struct feat_fd *ff,
2548 void *data __maybe_unused)
2549{
2550 if (do_read_u64(ff, &ff->ph->env.clockid_res_ns))
2551 return -1;
2552
2553 return 0;
2554}
2555
2534struct feature_ops { 2556struct feature_ops {
2535 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); 2557 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
2536 void (*print)(struct feat_fd *ff, FILE *fp); 2558 void (*print)(struct feat_fd *ff, FILE *fp);
@@ -2590,6 +2612,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
2590 FEAT_OPN(CACHE, cache, true), 2612 FEAT_OPN(CACHE, cache, true),
2591 FEAT_OPR(SAMPLE_TIME, sample_time, false), 2613 FEAT_OPR(SAMPLE_TIME, sample_time, false),
2592 FEAT_OPR(MEM_TOPOLOGY, mem_topology, true), 2614 FEAT_OPR(MEM_TOPOLOGY, mem_topology, true),
2615 FEAT_OPR(CLOCKID, clockid, false)
2593}; 2616};
2594 2617
2595struct header_print_data { 2618struct header_print_data {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index e17903caa71d..0d553ddca0a3 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -38,6 +38,7 @@ enum {
38 HEADER_CACHE, 38 HEADER_CACHE,
39 HEADER_SAMPLE_TIME, 39 HEADER_SAMPLE_TIME,
40 HEADER_MEM_TOPOLOGY, 40 HEADER_MEM_TOPOLOGY,
41 HEADER_CLOCKID,
41 HEADER_LAST_FEATURE, 42 HEADER_LAST_FEATURE,
42 HEADER_FEAT_BITS = 256, 43 HEADER_FEAT_BITS = 256,
43}; 44};
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index 7f0c83b6332b..7b27d77306c2 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -269,6 +269,13 @@ static int intel_bts_do_fix_overlap(struct auxtrace_queue *queue,
269 return 0; 269 return 0;
270} 270}
271 271
272static inline u8 intel_bts_cpumode(struct intel_bts *bts, uint64_t ip)
273{
274 return machine__kernel_ip(bts->machine, ip) ?
275 PERF_RECORD_MISC_KERNEL :
276 PERF_RECORD_MISC_USER;
277}
278
272static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq, 279static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
273 struct branch *branch) 280 struct branch *branch)
274{ 281{
@@ -281,12 +288,8 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
281 bts->num_events++ <= bts->synth_opts.initial_skip) 288 bts->num_events++ <= bts->synth_opts.initial_skip)
282 return 0; 289 return 0;
283 290
284 event.sample.header.type = PERF_RECORD_SAMPLE;
285 event.sample.header.misc = PERF_RECORD_MISC_USER;
286 event.sample.header.size = sizeof(struct perf_event_header);
287
288 sample.cpumode = PERF_RECORD_MISC_USER;
289 sample.ip = le64_to_cpu(branch->from); 291 sample.ip = le64_to_cpu(branch->from);
292 sample.cpumode = intel_bts_cpumode(bts, sample.ip);
290 sample.pid = btsq->pid; 293 sample.pid = btsq->pid;
291 sample.tid = btsq->tid; 294 sample.tid = btsq->tid;
292 sample.addr = le64_to_cpu(branch->to); 295 sample.addr = le64_to_cpu(branch->to);
@@ -298,6 +301,10 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
298 sample.insn_len = btsq->intel_pt_insn.length; 301 sample.insn_len = btsq->intel_pt_insn.length;
299 memcpy(sample.insn, btsq->intel_pt_insn.buf, INTEL_PT_INSN_BUF_SZ); 302 memcpy(sample.insn, btsq->intel_pt_insn.buf, INTEL_PT_INSN_BUF_SZ);
300 303
304 event.sample.header.type = PERF_RECORD_SAMPLE;
305 event.sample.header.misc = sample.cpumode;
306 event.sample.header.size = sizeof(struct perf_event_header);
307
301 if (bts->synth_opts.inject) { 308 if (bts->synth_opts.inject) {
302 event.sample.header.size = bts->branches_event_size; 309 event.sample.header.size = bts->branches_event_size;
303 ret = perf_event__synthesize_sample(&event, 310 ret = perf_event__synthesize_sample(&event,
@@ -910,7 +917,8 @@ int intel_bts_process_auxtrace_info(union perf_event *event,
910 if (session->itrace_synth_opts && session->itrace_synth_opts->set) { 917 if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
911 bts->synth_opts = *session->itrace_synth_opts; 918 bts->synth_opts = *session->itrace_synth_opts;
912 } else { 919 } else {
913 itrace_synth_opts__set_default(&bts->synth_opts); 920 itrace_synth_opts__set_default(&bts->synth_opts,
921 session->itrace_synth_opts->default_no_sample);
914 if (session->itrace_synth_opts) 922 if (session->itrace_synth_opts)
915 bts->synth_opts.thread_stack = 923 bts->synth_opts.thread_stack =
916 session->itrace_synth_opts->thread_stack; 924 session->itrace_synth_opts->thread_stack;
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 48c1d415c6b0..86cc9a64e982 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -407,6 +407,13 @@ intel_pt_cache_lookup(struct dso *dso, struct machine *machine, u64 offset)
407 return auxtrace_cache__lookup(dso->auxtrace_cache, offset); 407 return auxtrace_cache__lookup(dso->auxtrace_cache, offset);
408} 408}
409 409
410static inline u8 intel_pt_cpumode(struct intel_pt *pt, uint64_t ip)
411{
412 return ip >= pt->kernel_start ?
413 PERF_RECORD_MISC_KERNEL :
414 PERF_RECORD_MISC_USER;
415}
416
410static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn, 417static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
411 uint64_t *insn_cnt_ptr, uint64_t *ip, 418 uint64_t *insn_cnt_ptr, uint64_t *ip,
412 uint64_t to_ip, uint64_t max_insn_cnt, 419 uint64_t to_ip, uint64_t max_insn_cnt,
@@ -429,10 +436,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
429 if (to_ip && *ip == to_ip) 436 if (to_ip && *ip == to_ip)
430 goto out_no_cache; 437 goto out_no_cache;
431 438
432 if (*ip >= ptq->pt->kernel_start) 439 cpumode = intel_pt_cpumode(ptq->pt, *ip);
433 cpumode = PERF_RECORD_MISC_KERNEL;
434 else
435 cpumode = PERF_RECORD_MISC_USER;
436 440
437 thread = ptq->thread; 441 thread = ptq->thread;
438 if (!thread) { 442 if (!thread) {
@@ -759,7 +763,8 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
759 if (pt->synth_opts.callchain) { 763 if (pt->synth_opts.callchain) {
760 size_t sz = sizeof(struct ip_callchain); 764 size_t sz = sizeof(struct ip_callchain);
761 765
762 sz += pt->synth_opts.callchain_sz * sizeof(u64); 766 /* Add 1 to callchain_sz for callchain context */
767 sz += (pt->synth_opts.callchain_sz + 1) * sizeof(u64);
763 ptq->chain = zalloc(sz); 768 ptq->chain = zalloc(sz);
764 if (!ptq->chain) 769 if (!ptq->chain)
765 goto out_free; 770 goto out_free;
@@ -1058,15 +1063,11 @@ static void intel_pt_prep_b_sample(struct intel_pt *pt,
1058 union perf_event *event, 1063 union perf_event *event,
1059 struct perf_sample *sample) 1064 struct perf_sample *sample)
1060{ 1065{
1061 event->sample.header.type = PERF_RECORD_SAMPLE;
1062 event->sample.header.misc = PERF_RECORD_MISC_USER;
1063 event->sample.header.size = sizeof(struct perf_event_header);
1064
1065 if (!pt->timeless_decoding) 1066 if (!pt->timeless_decoding)
1066 sample->time = tsc_to_perf_time(ptq->timestamp, &pt->tc); 1067 sample->time = tsc_to_perf_time(ptq->timestamp, &pt->tc);
1067 1068
1068 sample->cpumode = PERF_RECORD_MISC_USER;
1069 sample->ip = ptq->state->from_ip; 1069 sample->ip = ptq->state->from_ip;
1070 sample->cpumode = intel_pt_cpumode(pt, sample->ip);
1070 sample->pid = ptq->pid; 1071 sample->pid = ptq->pid;
1071 sample->tid = ptq->tid; 1072 sample->tid = ptq->tid;
1072 sample->addr = ptq->state->to_ip; 1073 sample->addr = ptq->state->to_ip;
@@ -1075,6 +1076,10 @@ static void intel_pt_prep_b_sample(struct intel_pt *pt,
1075 sample->flags = ptq->flags; 1076 sample->flags = ptq->flags;
1076 sample->insn_len = ptq->insn_len; 1077 sample->insn_len = ptq->insn_len;
1077 memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ); 1078 memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
1079
1080 event->sample.header.type = PERF_RECORD_SAMPLE;
1081 event->sample.header.misc = sample->cpumode;
1082 event->sample.header.size = sizeof(struct perf_event_header);
1078} 1083}
1079 1084
1080static int intel_pt_inject_event(union perf_event *event, 1085static int intel_pt_inject_event(union perf_event *event,
@@ -1160,7 +1165,8 @@ static void intel_pt_prep_sample(struct intel_pt *pt,
1160 1165
1161 if (pt->synth_opts.callchain) { 1166 if (pt->synth_opts.callchain) {
1162 thread_stack__sample(ptq->thread, ptq->chain, 1167 thread_stack__sample(ptq->thread, ptq->chain,
1163 pt->synth_opts.callchain_sz, sample->ip); 1168 pt->synth_opts.callchain_sz + 1,
1169 sample->ip, pt->kernel_start);
1164 sample->callchain = ptq->chain; 1170 sample->callchain = ptq->chain;
1165 } 1171 }
1166 1172
@@ -2559,7 +2565,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2559 if (session->itrace_synth_opts && session->itrace_synth_opts->set) { 2565 if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
2560 pt->synth_opts = *session->itrace_synth_opts; 2566 pt->synth_opts = *session->itrace_synth_opts;
2561 } else { 2567 } else {
2562 itrace_synth_opts__set_default(&pt->synth_opts); 2568 itrace_synth_opts__set_default(&pt->synth_opts,
2569 session->itrace_synth_opts->default_no_sample);
2563 if (use_browser != -1) { 2570 if (use_browser != -1) {
2564 pt->synth_opts.branches = false; 2571 pt->synth_opts.branches = false;
2565 pt->synth_opts.callchain = true; 2572 pt->synth_opts.callchain = true;
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 111ae858cbcb..8f36ce813bc5 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1708,6 +1708,7 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1708 struct thread *parent = machine__findnew_thread(machine, 1708 struct thread *parent = machine__findnew_thread(machine,
1709 event->fork.ppid, 1709 event->fork.ppid,
1710 event->fork.ptid); 1710 event->fork.ptid);
1711 bool do_maps_clone = true;
1711 int err = 0; 1712 int err = 0;
1712 1713
1713 if (dump_trace) 1714 if (dump_trace)
@@ -1736,9 +1737,25 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1736 1737
1737 thread = machine__findnew_thread(machine, event->fork.pid, 1738 thread = machine__findnew_thread(machine, event->fork.pid,
1738 event->fork.tid); 1739 event->fork.tid);
1740 /*
1741 * When synthesizing FORK events, we are trying to create thread
1742 * objects for the already running tasks on the machine.
1743 *
1744 * Normally, for a kernel FORK event, we want to clone the parent's
1745 * maps because that is what the kernel just did.
1746 *
1747 * But when synthesizing, this should not be done. If we do, we end up
1748 * with overlapping maps as we process the sythesized MMAP2 events that
1749 * get delivered shortly thereafter.
1750 *
1751 * Use the FORK event misc flags in an internal way to signal this
1752 * situation, so we can elide the map clone when appropriate.
1753 */
1754 if (event->fork.header.misc & PERF_RECORD_MISC_FORK_EXEC)
1755 do_maps_clone = false;
1739 1756
1740 if (thread == NULL || parent == NULL || 1757 if (thread == NULL || parent == NULL ||
1741 thread__fork(thread, parent, sample->time) < 0) { 1758 thread__fork(thread, parent, sample->time, do_maps_clone) < 0) {
1742 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); 1759 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
1743 err = -1; 1760 err = -1;
1744 } 1761 }
@@ -2140,6 +2157,27 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
2140 return 0; 2157 return 0;
2141} 2158}
2142 2159
2160static int find_prev_cpumode(struct ip_callchain *chain, struct thread *thread,
2161 struct callchain_cursor *cursor,
2162 struct symbol **parent,
2163 struct addr_location *root_al,
2164 u8 *cpumode, int ent)
2165{
2166 int err = 0;
2167
2168 while (--ent >= 0) {
2169 u64 ip = chain->ips[ent];
2170
2171 if (ip >= PERF_CONTEXT_MAX) {
2172 err = add_callchain_ip(thread, cursor, parent,
2173 root_al, cpumode, ip,
2174 false, NULL, NULL, 0);
2175 break;
2176 }
2177 }
2178 return err;
2179}
2180
2143static int thread__resolve_callchain_sample(struct thread *thread, 2181static int thread__resolve_callchain_sample(struct thread *thread,
2144 struct callchain_cursor *cursor, 2182 struct callchain_cursor *cursor,
2145 struct perf_evsel *evsel, 2183 struct perf_evsel *evsel,
@@ -2246,6 +2284,12 @@ static int thread__resolve_callchain_sample(struct thread *thread,
2246 } 2284 }
2247 2285
2248check_calls: 2286check_calls:
2287 if (callchain_param.order != ORDER_CALLEE) {
2288 err = find_prev_cpumode(chain, thread, cursor, parent, root_al,
2289 &cpumode, chain->nr - first_call);
2290 if (err)
2291 return (err < 0) ? err : 0;
2292 }
2249 for (i = first_call, nr_entries = 0; 2293 for (i = first_call, nr_entries = 0;
2250 i < chain_nr && nr_entries < max_stack; i++) { 2294 i < chain_nr && nr_entries < max_stack; i++) {
2251 u64 ip; 2295 u64 ip;
@@ -2260,9 +2304,15 @@ check_calls:
2260 continue; 2304 continue;
2261#endif 2305#endif
2262 ip = chain->ips[j]; 2306 ip = chain->ips[j];
2263
2264 if (ip < PERF_CONTEXT_MAX) 2307 if (ip < PERF_CONTEXT_MAX)
2265 ++nr_entries; 2308 ++nr_entries;
2309 else if (callchain_param.order != ORDER_CALLEE) {
2310 err = find_prev_cpumode(chain, thread, cursor, parent,
2311 root_al, &cpumode, j);
2312 if (err)
2313 return (err < 0) ? err : 0;
2314 continue;
2315 }
2266 2316
2267 err = add_callchain_ip(thread, cursor, parent, 2317 err = add_callchain_ip(thread, cursor, parent,
2268 root_al, &cpumode, ip, 2318 root_al, &cpumode, ip,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index f8cd3e7c9186..59be3466d64d 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -926,6 +926,7 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
926 [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit", 926 [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit",
927 [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit", 927 [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit",
928 [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack", 928 [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack",
929 [PARSE_EVENTS__TERM_TYPE_MAX_EVENTS] = "nr",
929 [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", 930 [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite",
930 [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", 931 [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite",
931 [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config", 932 [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config",
@@ -1037,6 +1038,9 @@ do { \
1037 case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1038 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1038 CHECK_TYPE_VAL(NUM); 1039 CHECK_TYPE_VAL(NUM);
1039 break; 1040 break;
1041 case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
1042 CHECK_TYPE_VAL(NUM);
1043 break;
1040 default: 1044 default:
1041 err->str = strdup("unknown term"); 1045 err->str = strdup("unknown term");
1042 err->idx = term->err_term; 1046 err->idx = term->err_term;
@@ -1084,6 +1088,7 @@ static int config_term_tracepoint(struct perf_event_attr *attr,
1084 case PARSE_EVENTS__TERM_TYPE_INHERIT: 1088 case PARSE_EVENTS__TERM_TYPE_INHERIT:
1085 case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1089 case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
1086 case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1090 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1091 case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
1087 case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1092 case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1088 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 1093 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1089 return config_term_common(attr, term, err); 1094 return config_term_common(attr, term, err);
@@ -1162,6 +1167,9 @@ do { \
1162 case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1167 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1163 ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num); 1168 ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num);
1164 break; 1169 break;
1170 case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
1171 ADD_CONFIG_TERM(MAX_EVENTS, max_events, term->val.num);
1172 break;
1165 case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1173 case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1166 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0); 1174 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0);
1167 break; 1175 break;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 4473dac27aee..5ed035cbcbb7 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -71,6 +71,7 @@ enum {
71 PARSE_EVENTS__TERM_TYPE_NOINHERIT, 71 PARSE_EVENTS__TERM_TYPE_NOINHERIT,
72 PARSE_EVENTS__TERM_TYPE_INHERIT, 72 PARSE_EVENTS__TERM_TYPE_INHERIT,
73 PARSE_EVENTS__TERM_TYPE_MAX_STACK, 73 PARSE_EVENTS__TERM_TYPE_MAX_STACK,
74 PARSE_EVENTS__TERM_TYPE_MAX_EVENTS,
74 PARSE_EVENTS__TERM_TYPE_NOOVERWRITE, 75 PARSE_EVENTS__TERM_TYPE_NOOVERWRITE,
75 PARSE_EVENTS__TERM_TYPE_OVERWRITE, 76 PARSE_EVENTS__TERM_TYPE_OVERWRITE,
76 PARSE_EVENTS__TERM_TYPE_DRV_CFG, 77 PARSE_EVENTS__TERM_TYPE_DRV_CFG,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 5f761f3ed0f3..7805c71aaae2 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -269,6 +269,7 @@ time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
269call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } 269call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
270stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } 270stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
271max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); } 271max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); }
272nr { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_EVENTS); }
272inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } 273inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); }
273no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } 274no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
274overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); } 275overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); }
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 0281d5e2cd67..66a84d5846c8 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -324,7 +324,17 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
324 plt_entry_size = 16; 324 plt_entry_size = 16;
325 break; 325 break;
326 326
327 default: /* FIXME: s390/alpha/mips/parisc/poperpc/sh/sparc/xtensa need to be checked */ 327 case EM_SPARC:
328 plt_header_size = 48;
329 plt_entry_size = 12;
330 break;
331
332 case EM_SPARCV9:
333 plt_header_size = 128;
334 plt_entry_size = 32;
335 break;
336
337 default: /* FIXME: s390/alpha/mips/parisc/poperpc/sh/xtensa need to be checked */
328 plt_header_size = shdr_plt.sh_entsize; 338 plt_header_size = shdr_plt.sh_entsize;
329 plt_entry_size = shdr_plt.sh_entsize; 339 plt_entry_size = shdr_plt.sh_entsize;
330 break; 340 break;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 20f49779116b..d026d215bdc6 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -123,7 +123,8 @@ struct symbol_conf {
123 const char *vmlinux_name, 123 const char *vmlinux_name,
124 *kallsyms_name, 124 *kallsyms_name,
125 *source_prefix, 125 *source_prefix,
126 *field_sep; 126 *field_sep,
127 *graph_function;
127 const char *default_guest_vmlinux_name, 128 const char *default_guest_vmlinux_name,
128 *default_guest_kallsyms, 129 *default_guest_kallsyms,
129 *default_guest_modules; 130 *default_guest_modules;
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index c091635bf7dc..61a4286a74dc 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -310,20 +310,46 @@ void thread_stack__free(struct thread *thread)
310 } 310 }
311} 311}
312 312
313static inline u64 callchain_context(u64 ip, u64 kernel_start)
314{
315 return ip < kernel_start ? PERF_CONTEXT_USER : PERF_CONTEXT_KERNEL;
316}
317
313void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, 318void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
314 size_t sz, u64 ip) 319 size_t sz, u64 ip, u64 kernel_start)
315{ 320{
316 size_t i; 321 u64 context = callchain_context(ip, kernel_start);
322 u64 last_context;
323 size_t i, j;
317 324
318 if (!thread || !thread->ts) 325 if (sz < 2) {
319 chain->nr = 1; 326 chain->nr = 0;
320 else 327 return;
321 chain->nr = min(sz, thread->ts->cnt + 1); 328 }
322 329
323 chain->ips[0] = ip; 330 chain->ips[0] = context;
331 chain->ips[1] = ip;
332
333 if (!thread || !thread->ts) {
334 chain->nr = 2;
335 return;
336 }
337
338 last_context = context;
339
340 for (i = 2, j = 1; i < sz && j <= thread->ts->cnt; i++, j++) {
341 ip = thread->ts->stack[thread->ts->cnt - j].ret_addr;
342 context = callchain_context(ip, kernel_start);
343 if (context != last_context) {
344 if (i >= sz - 1)
345 break;
346 chain->ips[i++] = context;
347 last_context = context;
348 }
349 chain->ips[i] = ip;
350 }
324 351
325 for (i = 1; i < chain->nr; i++) 352 chain->nr = i;
326 chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr;
327} 353}
328 354
329struct call_return_processor * 355struct call_return_processor *
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h
index b7e41c4ebfdd..f97c00a8c251 100644
--- a/tools/perf/util/thread-stack.h
+++ b/tools/perf/util/thread-stack.h
@@ -84,7 +84,7 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
84 u64 to_ip, u16 insn_len, u64 trace_nr); 84 u64 to_ip, u16 insn_len, u64 trace_nr);
85void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr); 85void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr);
86void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, 86void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
87 size_t sz, u64 ip); 87 size_t sz, u64 ip, u64 kernel_start);
88int thread_stack__flush(struct thread *thread); 88int thread_stack__flush(struct thread *thread);
89void thread_stack__free(struct thread *thread); 89void thread_stack__free(struct thread *thread);
90size_t thread_stack__depth(struct thread *thread); 90size_t thread_stack__depth(struct thread *thread);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 2048d393ece6..3d9ed7d0e281 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -330,7 +330,8 @@ static int thread__prepare_access(struct thread *thread)
330} 330}
331 331
332static int thread__clone_map_groups(struct thread *thread, 332static int thread__clone_map_groups(struct thread *thread,
333 struct thread *parent) 333 struct thread *parent,
334 bool do_maps_clone)
334{ 335{
335 /* This is new thread, we share map groups for process. */ 336 /* This is new thread, we share map groups for process. */
336 if (thread->pid_ == parent->pid_) 337 if (thread->pid_ == parent->pid_)
@@ -341,15 +342,11 @@ static int thread__clone_map_groups(struct thread *thread,
341 thread->pid_, thread->tid, parent->pid_, parent->tid); 342 thread->pid_, thread->tid, parent->pid_, parent->tid);
342 return 0; 343 return 0;
343 } 344 }
344
345 /* But this one is new process, copy maps. */ 345 /* But this one is new process, copy maps. */
346 if (map_groups__clone(thread, parent->mg) < 0) 346 return do_maps_clone ? map_groups__clone(thread, parent->mg) : 0;
347 return -ENOMEM;
348
349 return 0;
350} 347}
351 348
352int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) 349int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone)
353{ 350{
354 if (parent->comm_set) { 351 if (parent->comm_set) {
355 const char *comm = thread__comm_str(parent); 352 const char *comm = thread__comm_str(parent);
@@ -362,7 +359,7 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
362 } 359 }
363 360
364 thread->ppid = parent->tid; 361 thread->ppid = parent->tid;
365 return thread__clone_map_groups(thread, parent); 362 return thread__clone_map_groups(thread, parent, do_maps_clone);
366} 363}
367 364
368void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, 365void thread__find_cpumode_addr_location(struct thread *thread, u64 addr,
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 07606aa6998d..30e2b4c165fe 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -42,6 +42,8 @@ struct thread {
42 void *addr_space; 42 void *addr_space;
43 struct unwind_libunwind_ops *unwind_libunwind_ops; 43 struct unwind_libunwind_ops *unwind_libunwind_ops;
44#endif 44#endif
45 bool filter;
46 int filter_entry_depth;
45}; 47};
46 48
47struct machine; 49struct machine;
@@ -87,7 +89,7 @@ struct comm *thread__comm(const struct thread *thread);
87struct comm *thread__exec_comm(const struct thread *thread); 89struct comm *thread__exec_comm(const struct thread *thread);
88const char *thread__comm_str(const struct thread *thread); 90const char *thread__comm_str(const struct thread *thread);
89int thread__insert_map(struct thread *thread, struct map *map); 91int thread__insert_map(struct thread *thread, struct map *map);
90int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); 92int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone);
91size_t thread__fprintf(struct thread *thread, FILE *fp); 93size_t thread__fprintf(struct thread *thread, FILE *fp);
92 94
93struct thread *thread__main_thread(struct machine *machine, struct thread *thread); 95struct thread *thread__main_thread(struct machine *machine, struct thread *thread);
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 6f318b15950e..5eff9bfc5758 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -45,13 +45,13 @@ static int __report_module(struct addr_location *al, u64 ip,
45 Dwarf_Addr s; 45 Dwarf_Addr s;
46 46
47 dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL); 47 dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL);
48 if (s != al->map->start) 48 if (s != al->map->start - al->map->pgoff)
49 mod = 0; 49 mod = 0;
50 } 50 }
51 51
52 if (!mod) 52 if (!mod)
53 mod = dwfl_report_elf(ui->dwfl, dso->short_name, 53 mod = dwfl_report_elf(ui->dwfl, dso->short_name,
54 (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start, 54 (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start - al->map->pgoff,
55 false); 55 false);
56 56
57 return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1; 57 return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1;