1
0
Fork 0

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf updates and fixes from Ingo Molnar:
 "These are almost all tooling updates: 'perf top', 'perf trace' and
  'perf script' fixes and updates, an UAPI header sync with the merge
  window versions, license marker updates, much improved Sparc support
  from David Miller, and a number of fixes"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (66 commits)
  perf intel-pt/bts: Calculate cpumode for synthesized samples
  perf intel-pt: Insert callchain context into synthesized callchains
  perf tools: Don't clone maps from parent when synthesizing forks
  perf top: Start display thread earlier
  tools headers uapi: Update linux/if_link.h header copy
  tools headers uapi: Update linux/netlink.h header copy
  tools headers: Sync the various kvm.h header copies
  tools include uapi: Update linux/mmap.h copy
  perf trace beauty: Use the mmap flags table generated from headers
  perf beauty: Wire up the mmap flags table generator to the Makefile
  perf beauty: Add a generator for MAP_ mmap's flag constants
  tools include uapi: Update asound.h copy
  tools arch uapi: Update asm-generic/unistd.h and arm64 unistd.h copies
  tools include uapi: Update linux/fs.h copy
  perf callchain: Honour the ordering of PERF_CONTEXT_{USER,KERNEL,etc}
  perf cs-etm: Correct CPU mode for samples
  perf unwind: Take pgoff into account when reporting elf to libdwfl
  perf top: Do not use overwrite mode by default
  perf top: Allow disabling the overwrite mode
  perf trace: Beautify mount's first pathname arg
  ...
hifive-unleashed-5.1
Linus Torvalds 2018-11-03 18:13:43 -07:00
commit 01897f3e05
102 changed files with 3617 additions and 540 deletions

View File

@ -646,10 +646,12 @@ struct perf_event_mmap_page {
* *
* PERF_RECORD_MISC_MMAP_DATA - PERF_RECORD_MMAP* events * PERF_RECORD_MISC_MMAP_DATA - PERF_RECORD_MMAP* events
* PERF_RECORD_MISC_COMM_EXEC - PERF_RECORD_COMM event * PERF_RECORD_MISC_COMM_EXEC - PERF_RECORD_COMM event
* PERF_RECORD_MISC_FORK_EXEC - PERF_RECORD_FORK event (perf internal)
* PERF_RECORD_MISC_SWITCH_OUT - PERF_RECORD_SWITCH* events * PERF_RECORD_MISC_SWITCH_OUT - PERF_RECORD_SWITCH* events
*/ */
#define PERF_RECORD_MISC_MMAP_DATA (1 << 13) #define PERF_RECORD_MISC_MMAP_DATA (1 << 13)
#define PERF_RECORD_MISC_COMM_EXEC (1 << 13) #define PERF_RECORD_MISC_COMM_EXEC (1 << 13)
#define PERF_RECORD_MISC_FORK_EXEC (1 << 13)
#define PERF_RECORD_MISC_SWITCH_OUT (1 << 13) #define PERF_RECORD_MISC_SWITCH_OUT (1 << 13)
/* /*
* These PERF_RECORD_MISC_* flags below are safely reused * These PERF_RECORD_MISC_* flags below are safely reused

View File

@ -750,7 +750,7 @@ static inline void update_cgrp_time_from_event(struct perf_event *event)
/* /*
* Do not update time when cgroup is not active * Do not update time when cgroup is not active
*/ */
if (cgroup_is_descendant(cgrp->css.cgroup, event->cgrp->css.cgroup)) if (cgroup_is_descendant(cgrp->css.cgroup, event->cgrp->css.cgroup))
__update_cgrp_time(event->cgrp); __update_cgrp_time(event->cgrp);
} }

View File

@ -16,5 +16,6 @@
*/ */
#define __ARCH_WANT_RENAMEAT #define __ARCH_WANT_RENAMEAT
#define __ARCH_WANT_NEW_STAT
#include <asm-generic/unistd.h> #include <asm-generic/unistd.h>

View File

@ -634,6 +634,7 @@ struct kvm_ppc_cpu_char {
#define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe) #define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe)
#define KVM_REG_PPC_ONLINE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbf) #define KVM_REG_PPC_ONLINE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbf)
#define KVM_REG_PPC_PTCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc0)
/* Transactional Memory checkpointed state: /* Transactional Memory checkpointed state:
* This is all GPRs, all VSX regs and a subset of SPRs * This is all GPRs, all VSX regs and a subset of SPRs

View File

@ -160,6 +160,8 @@ struct kvm_s390_vm_cpu_subfunc {
#define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1 #define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1
#define KVM_S390_VM_CRYPTO_DISABLE_AES_KW 2 #define KVM_S390_VM_CRYPTO_DISABLE_AES_KW 2
#define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW 3 #define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW 3
#define KVM_S390_VM_CRYPTO_ENABLE_APIE 4
#define KVM_S390_VM_CRYPTO_DISABLE_APIE 5
/* kvm attributes for migration mode */ /* kvm attributes for migration mode */
#define KVM_S390_VM_MIGRATION_STOP 0 #define KVM_S390_VM_MIGRATION_STOP 0

View File

@ -300,10 +300,7 @@ struct kvm_vcpu_events {
__u8 injected; __u8 injected;
__u8 nr; __u8 nr;
__u8 has_error_code; __u8 has_error_code;
union { __u8 pending;
__u8 pad;
__u8 pending;
};
__u32 error_code; __u32 error_code;
} exception; } exception;
struct { struct {
@ -387,6 +384,7 @@ struct kvm_sync_regs {
#define KVM_STATE_NESTED_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_GUEST_MODE 0x00000001
#define KVM_STATE_NESTED_RUN_PENDING 0x00000002 #define KVM_STATE_NESTED_RUN_PENDING 0x00000002
#define KVM_STATE_NESTED_EVMCS 0x00000004
#define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001
#define KVM_STATE_NESTED_SMM_VMXON 0x00000002 #define KVM_STATE_NESTED_SMM_VMXON 0x00000002

View File

@ -242,10 +242,12 @@ __SYSCALL(__NR_tee, sys_tee)
/* fs/stat.c */ /* fs/stat.c */
#define __NR_readlinkat 78 #define __NR_readlinkat 78
__SYSCALL(__NR_readlinkat, sys_readlinkat) __SYSCALL(__NR_readlinkat, sys_readlinkat)
#if defined(__ARCH_WANT_NEW_STAT) || defined(__ARCH_WANT_STAT64)
#define __NR3264_fstatat 79 #define __NR3264_fstatat 79
__SC_3264(__NR3264_fstatat, sys_fstatat64, sys_newfstatat) __SC_3264(__NR3264_fstatat, sys_fstatat64, sys_newfstatat)
#define __NR3264_fstat 80 #define __NR3264_fstat 80
__SC_3264(__NR3264_fstat, sys_fstat64, sys_newfstat) __SC_3264(__NR3264_fstat, sys_fstat64, sys_newfstat)
#endif
/* fs/sync.c */ /* fs/sync.c */
#define __NR_sync 81 #define __NR_sync 81

View File

@ -0,0 +1,393 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI_LINUX_FS_H
#define _UAPI_LINUX_FS_H
/*
* This file has definitions for some important file table structures
* and constants and structures used by various generic file system
* ioctl's. Please do not make any changes in this file before
* sending patches for review to linux-fsdevel@vger.kernel.org and
* linux-api@vger.kernel.org.
*/
#include <linux/limits.h>
#include <linux/ioctl.h>
#include <linux/types.h>
/*
* It's silly to have NR_OPEN bigger than NR_FILE, but you can change
* the file limit at runtime and only root can increase the per-process
* nr_file rlimit, so it's safe to set up a ridiculously high absolute
* upper limit on files-per-process.
*
* Some programs (notably those using select()) may have to be
* recompiled to take full advantage of the new limits..
*/
/* Fixed constants first: */
#undef NR_OPEN
#define INR_OPEN_CUR 1024 /* Initial setting for nfile rlimits */
#define INR_OPEN_MAX 4096 /* Hard limit for nfile rlimits */
#define BLOCK_SIZE_BITS 10
#define BLOCK_SIZE (1<<BLOCK_SIZE_BITS)
#define SEEK_SET 0 /* seek relative to beginning of file */
#define SEEK_CUR 1 /* seek relative to current file position */
#define SEEK_END 2 /* seek relative to end of file */
#define SEEK_DATA 3 /* seek to the next data */
#define SEEK_HOLE 4 /* seek to the next hole */
#define SEEK_MAX SEEK_HOLE
#define RENAME_NOREPLACE (1 << 0) /* Don't overwrite target */
#define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */
#define RENAME_WHITEOUT (1 << 2) /* Whiteout source */
struct file_clone_range {
__s64 src_fd;
__u64 src_offset;
__u64 src_length;
__u64 dest_offset;
};
struct fstrim_range {
__u64 start;
__u64 len;
__u64 minlen;
};
/* extent-same (dedupe) ioctls; these MUST match the btrfs ioctl definitions */
#define FILE_DEDUPE_RANGE_SAME 0
#define FILE_DEDUPE_RANGE_DIFFERS 1
/* from struct btrfs_ioctl_file_extent_same_info */
struct file_dedupe_range_info {
__s64 dest_fd; /* in - destination file */
__u64 dest_offset; /* in - start of extent in destination */
__u64 bytes_deduped; /* out - total # of bytes we were able
* to dedupe from this file. */
/* status of this dedupe operation:
* < 0 for error
* == FILE_DEDUPE_RANGE_SAME if dedupe succeeds
* == FILE_DEDUPE_RANGE_DIFFERS if data differs
*/
__s32 status; /* out - see above description */
__u32 reserved; /* must be zero */
};
/* from struct btrfs_ioctl_file_extent_same_args */
struct file_dedupe_range {
__u64 src_offset; /* in - start of extent in source */
__u64 src_length; /* in - length of extent */
__u16 dest_count; /* in - total elements in info array */
__u16 reserved1; /* must be zero */
__u32 reserved2; /* must be zero */
struct file_dedupe_range_info info[0];
};
/* And dynamically-tunable limits and defaults: */
struct files_stat_struct {
unsigned long nr_files; /* read only */
unsigned long nr_free_files; /* read only */
unsigned long max_files; /* tunable */
};
struct inodes_stat_t {
long nr_inodes;
long nr_unused;
long dummy[5]; /* padding for sysctl ABI compatibility */
};
#define NR_FILE 8192 /* this can well be larger on a larger system */
/*
* These are the fs-independent mount-flags: up to 32 flags are supported
*/
#define MS_RDONLY 1 /* Mount read-only */
#define MS_NOSUID 2 /* Ignore suid and sgid bits */
#define MS_NODEV 4 /* Disallow access to device special files */
#define MS_NOEXEC 8 /* Disallow program execution */
#define MS_SYNCHRONOUS 16 /* Writes are synced at once */
#define MS_REMOUNT 32 /* Alter flags of a mounted FS */
#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */
#define MS_DIRSYNC 128 /* Directory modifications are synchronous */
#define MS_NOATIME 1024 /* Do not update access times. */
#define MS_NODIRATIME 2048 /* Do not update directory access times */
#define MS_BIND 4096
#define MS_MOVE 8192
#define MS_REC 16384
#define MS_VERBOSE 32768 /* War is peace. Verbosity is silence.
MS_VERBOSE is deprecated. */
#define MS_SILENT 32768
#define MS_POSIXACL (1<<16) /* VFS does not apply the umask */
#define MS_UNBINDABLE (1<<17) /* change to unbindable */
#define MS_PRIVATE (1<<18) /* change to private */
#define MS_SLAVE (1<<19) /* change to slave */
#define MS_SHARED (1<<20) /* change to shared */
#define MS_RELATIME (1<<21) /* Update atime relative to mtime/ctime. */
#define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */
#define MS_I_VERSION (1<<23) /* Update inode I_version field */
#define MS_STRICTATIME (1<<24) /* Always perform atime updates */
#define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */
/* These sb flags are internal to the kernel */
#define MS_SUBMOUNT (1<<26)
#define MS_NOREMOTELOCK (1<<27)
#define MS_NOSEC (1<<28)
#define MS_BORN (1<<29)
#define MS_ACTIVE (1<<30)
#define MS_NOUSER (1<<31)
/*
* Superblock flags that can be altered by MS_REMOUNT
*/
#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|\
MS_LAZYTIME)
/*
* Old magic mount flag and mask
*/
#define MS_MGC_VAL 0xC0ED0000
#define MS_MGC_MSK 0xffff0000
/*
* Structure for FS_IOC_FSGETXATTR[A] and FS_IOC_FSSETXATTR.
*/
struct fsxattr {
__u32 fsx_xflags; /* xflags field value (get/set) */
__u32 fsx_extsize; /* extsize field value (get/set)*/
__u32 fsx_nextents; /* nextents field value (get) */
__u32 fsx_projid; /* project identifier (get/set) */
__u32 fsx_cowextsize; /* CoW extsize field value (get/set)*/
unsigned char fsx_pad[8];
};
/*
* Flags for the fsx_xflags field
*/
#define FS_XFLAG_REALTIME 0x00000001 /* data in realtime volume */
#define FS_XFLAG_PREALLOC 0x00000002 /* preallocated file extents */
#define FS_XFLAG_IMMUTABLE 0x00000008 /* file cannot be modified */
#define FS_XFLAG_APPEND 0x00000010 /* all writes append */
#define FS_XFLAG_SYNC 0x00000020 /* all writes synchronous */
#define FS_XFLAG_NOATIME 0x00000040 /* do not update access time */
#define FS_XFLAG_NODUMP 0x00000080 /* do not include in backups */
#define FS_XFLAG_RTINHERIT 0x00000100 /* create with rt bit set */
#define FS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */
#define FS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */
#define FS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */
#define FS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */
#define FS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */
#define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */
#define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */
#define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */
#define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */
/* the read-only stuff doesn't really belong here, but any other place is
probably as bad and I don't want to create yet another include file. */
#define BLKROSET _IO(0x12,93) /* set device read-only (0 = read-write) */
#define BLKROGET _IO(0x12,94) /* get read-only status (0 = read_write) */
#define BLKRRPART _IO(0x12,95) /* re-read partition table */
#define BLKGETSIZE _IO(0x12,96) /* return device size /512 (long *arg) */
#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
#define BLKRASET _IO(0x12,98) /* set read ahead for block device */
#define BLKRAGET _IO(0x12,99) /* get current read ahead setting */
#define BLKFRASET _IO(0x12,100)/* set filesystem (mm/filemap.c) read-ahead */
#define BLKFRAGET _IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */
#define BLKSECTSET _IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */
#define BLKSECTGET _IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
#define BLKSSZGET _IO(0x12,104)/* get block device sector size */
#if 0
#define BLKPG _IO(0x12,105)/* See blkpg.h */
/* Some people are morons. Do not use sizeof! */
#define BLKELVGET _IOR(0x12,106,size_t)/* elevator get */
#define BLKELVSET _IOW(0x12,107,size_t)/* elevator set */
/* This was here just to show that the number is taken -
probably all these _IO(0x12,*) ioctls should be moved to blkpg.h. */
#endif
/* A jump here: 108-111 have been used for various private purposes. */
#define BLKBSZGET _IOR(0x12,112,size_t)
#define BLKBSZSET _IOW(0x12,113,size_t)
#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
#define BLKTRACESETUP _IOWR(0x12,115,struct blk_user_trace_setup)
#define BLKTRACESTART _IO(0x12,116)
#define BLKTRACESTOP _IO(0x12,117)
#define BLKTRACETEARDOWN _IO(0x12,118)
#define BLKDISCARD _IO(0x12,119)
#define BLKIOMIN _IO(0x12,120)
#define BLKIOOPT _IO(0x12,121)
#define BLKALIGNOFF _IO(0x12,122)
#define BLKPBSZGET _IO(0x12,123)
#define BLKDISCARDZEROES _IO(0x12,124)
#define BLKSECDISCARD _IO(0x12,125)
#define BLKROTATIONAL _IO(0x12,126)
#define BLKZEROOUT _IO(0x12,127)
/*
* A jump here: 130-131 are reserved for zoned block devices
* (see uapi/linux/blkzoned.h)
*/
#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
#define FIBMAP _IO(0x00,1) /* bmap access */
#define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */
#define FIFREEZE _IOWR('X', 119, int) /* Freeze */
#define FITHAW _IOWR('X', 120, int) /* Thaw */
#define FITRIM _IOWR('X', 121, struct fstrim_range) /* Trim */
#define FICLONE _IOW(0x94, 9, int)
#define FICLONERANGE _IOW(0x94, 13, struct file_clone_range)
#define FIDEDUPERANGE _IOWR(0x94, 54, struct file_dedupe_range)
#define FSLABEL_MAX 256 /* Max chars for the interface; each fs may differ */
#define FS_IOC_GETFLAGS _IOR('f', 1, long)
#define FS_IOC_SETFLAGS _IOW('f', 2, long)
#define FS_IOC_GETVERSION _IOR('v', 1, long)
#define FS_IOC_SETVERSION _IOW('v', 2, long)
#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap)
#define FS_IOC32_GETFLAGS _IOR('f', 1, int)
#define FS_IOC32_SETFLAGS _IOW('f', 2, int)
#define FS_IOC32_GETVERSION _IOR('v', 1, int)
#define FS_IOC32_SETVERSION _IOW('v', 2, int)
#define FS_IOC_FSGETXATTR _IOR('X', 31, struct fsxattr)
#define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr)
#define FS_IOC_GETFSLABEL _IOR(0x94, 49, char[FSLABEL_MAX])
#define FS_IOC_SETFSLABEL _IOW(0x94, 50, char[FSLABEL_MAX])
/*
* File system encryption support
*/
/* Policy provided via an ioctl on the topmost directory */
#define FS_KEY_DESCRIPTOR_SIZE 8
#define FS_POLICY_FLAGS_PAD_4 0x00
#define FS_POLICY_FLAGS_PAD_8 0x01
#define FS_POLICY_FLAGS_PAD_16 0x02
#define FS_POLICY_FLAGS_PAD_32 0x03
#define FS_POLICY_FLAGS_PAD_MASK 0x03
#define FS_POLICY_FLAGS_VALID 0x03
/* Encryption algorithms */
#define FS_ENCRYPTION_MODE_INVALID 0
#define FS_ENCRYPTION_MODE_AES_256_XTS 1
#define FS_ENCRYPTION_MODE_AES_256_GCM 2
#define FS_ENCRYPTION_MODE_AES_256_CBC 3
#define FS_ENCRYPTION_MODE_AES_256_CTS 4
#define FS_ENCRYPTION_MODE_AES_128_CBC 5
#define FS_ENCRYPTION_MODE_AES_128_CTS 6
#define FS_ENCRYPTION_MODE_SPECK128_256_XTS 7 /* Removed, do not use. */
#define FS_ENCRYPTION_MODE_SPECK128_256_CTS 8 /* Removed, do not use. */
struct fscrypt_policy {
__u8 version;
__u8 contents_encryption_mode;
__u8 filenames_encryption_mode;
__u8 flags;
__u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
};
#define FS_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct fscrypt_policy)
#define FS_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16])
#define FS_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct fscrypt_policy)
/* Parameters for passing an encryption key into the kernel keyring */
#define FS_KEY_DESC_PREFIX "fscrypt:"
#define FS_KEY_DESC_PREFIX_SIZE 8
/* Structure that userspace passes to the kernel keyring */
#define FS_MAX_KEY_SIZE 64
struct fscrypt_key {
__u32 mode;
__u8 raw[FS_MAX_KEY_SIZE];
__u32 size;
};
/*
* Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)
*
* Note: for historical reasons, these flags were originally used and
* defined for use by ext2/ext3, and then other file systems started
* using these flags so they wouldn't need to write their own version
* of chattr/lsattr (which was shipped as part of e2fsprogs). You
* should think twice before trying to use these flags in new
* contexts, or trying to assign these flags, since they are used both
* as the UAPI and the on-disk encoding for ext2/3/4. Also, we are
* almost out of 32-bit flags. :-)
*
* We have recently hoisted FS_IOC_FSGETXATTR / FS_IOC_FSSETXATTR from
* XFS to the generic FS level interface. This uses a structure that
* has padding and hence has more room to grow, so it may be more
* appropriate for many new use cases.
*
* Please do not change these flags or interfaces before checking with
* linux-fsdevel@vger.kernel.org and linux-api@vger.kernel.org.
*/
#define FS_SECRM_FL 0x00000001 /* Secure deletion */
#define FS_UNRM_FL 0x00000002 /* Undelete */
#define FS_COMPR_FL 0x00000004 /* Compress file */
#define FS_SYNC_FL 0x00000008 /* Synchronous updates */
#define FS_IMMUTABLE_FL 0x00000010 /* Immutable file */
#define FS_APPEND_FL 0x00000020 /* writes to file may only append */
#define FS_NODUMP_FL 0x00000040 /* do not dump file */
#define FS_NOATIME_FL 0x00000080 /* do not update atime */
/* Reserved for compression usage... */
#define FS_DIRTY_FL 0x00000100
#define FS_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
#define FS_NOCOMP_FL 0x00000400 /* Don't compress */
/* End compression flags --- maybe not all used */
#define FS_ENCRYPT_FL 0x00000800 /* Encrypted file */
#define FS_BTREE_FL 0x00001000 /* btree format dir */
#define FS_INDEX_FL 0x00001000 /* hash-indexed directory */
#define FS_IMAGIC_FL 0x00002000 /* AFS directory */
#define FS_JOURNAL_DATA_FL 0x00004000 /* Reserved for ext3 */
#define FS_NOTAIL_FL 0x00008000 /* file tail should not be merged */
#define FS_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
#define FS_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
#define FS_HUGE_FILE_FL 0x00040000 /* Reserved for ext4 */
#define FS_EXTENT_FL 0x00080000 /* Extents */
#define FS_EA_INODE_FL 0x00200000 /* Inode used for large EA */
#define FS_EOFBLOCKS_FL 0x00400000 /* Reserved for ext4 */
#define FS_NOCOW_FL 0x00800000 /* Do not cow file */
#define FS_INLINE_DATA_FL 0x10000000 /* Reserved for ext4 */
#define FS_PROJINHERIT_FL 0x20000000 /* Create with parents projid */
#define FS_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
#define FS_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */
#define FS_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */
#define SYNC_FILE_RANGE_WAIT_BEFORE 1
#define SYNC_FILE_RANGE_WRITE 2
#define SYNC_FILE_RANGE_WAIT_AFTER 4
/*
* Flags for preadv2/pwritev2:
*/
typedef int __bitwise __kernel_rwf_t;
/* high priority request, poll if possible */
#define RWF_HIPRI ((__force __kernel_rwf_t)0x00000001)
/* per-IO O_DSYNC */
#define RWF_DSYNC ((__force __kernel_rwf_t)0x00000002)
/* per-IO O_SYNC */
#define RWF_SYNC ((__force __kernel_rwf_t)0x00000004)
/* per-IO, return -EAGAIN if operation would block */
#define RWF_NOWAIT ((__force __kernel_rwf_t)0x00000008)
/* per-IO O_APPEND */
#define RWF_APPEND ((__force __kernel_rwf_t)0x00000010)
/* mask of flags supported by the kernel */
#define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT |\
RWF_APPEND)
#endif /* _UAPI_LINUX_FS_H */

View File

@ -287,6 +287,7 @@ enum {
IFLA_BR_MCAST_STATS_ENABLED, IFLA_BR_MCAST_STATS_ENABLED,
IFLA_BR_MCAST_IGMP_VERSION, IFLA_BR_MCAST_IGMP_VERSION,
IFLA_BR_MCAST_MLD_VERSION, IFLA_BR_MCAST_MLD_VERSION,
IFLA_BR_VLAN_STATS_PER_PORT,
__IFLA_BR_MAX, __IFLA_BR_MAX,
}; };

View File

@ -420,13 +420,19 @@ struct kvm_run {
struct kvm_coalesced_mmio_zone { struct kvm_coalesced_mmio_zone {
__u64 addr; __u64 addr;
__u32 size; __u32 size;
__u32 pad; union {
__u32 pad;
__u32 pio;
};
}; };
struct kvm_coalesced_mmio { struct kvm_coalesced_mmio {
__u64 phys_addr; __u64 phys_addr;
__u32 len; __u32 len;
__u32 pad; union {
__u32 pad;
__u32 pio;
};
__u8 data[8]; __u8 data[8];
}; };
@ -751,6 +757,15 @@ struct kvm_ppc_resize_hpt {
#define KVM_S390_SIE_PAGE_OFFSET 1 #define KVM_S390_SIE_PAGE_OFFSET 1
/*
* On arm64, machine type can be used to request the physical
* address size for the VM. Bits[7-0] are reserved for the guest
* PA size shift (i.e, log2(PA_Size)). For backward compatibility,
* value 0 implies the default IPA size, 40bits.
*/
#define KVM_VM_TYPE_ARM_IPA_SIZE_MASK 0xffULL
#define KVM_VM_TYPE_ARM_IPA_SIZE(x) \
((x) & KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
/* /*
* ioctls for /dev/kvm fds: * ioctls for /dev/kvm fds:
*/ */
@ -958,6 +973,8 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_HYPERV_SEND_IPI 161 #define KVM_CAP_HYPERV_SEND_IPI 161
#define KVM_CAP_COALESCED_PIO 162 #define KVM_CAP_COALESCED_PIO 162
#define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163 #define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163
#define KVM_CAP_EXCEPTION_PAYLOAD 164
#define KVM_CAP_ARM_VM_IPA_SIZE 165
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING

View File

@ -28,7 +28,9 @@
#define MAP_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB #define MAP_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB
#define MAP_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB #define MAP_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB
#define MAP_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB #define MAP_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB
#define MAP_HUGE_32MB HUGETLB_FLAG_ENCODE_32MB
#define MAP_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB #define MAP_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB
#define MAP_HUGE_512MB HUGETLB_FLAG_ENCODE_512MB
#define MAP_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB #define MAP_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB
#define MAP_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB #define MAP_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB
#define MAP_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB #define MAP_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB

View File

@ -155,6 +155,7 @@ enum nlmsgerr_attrs {
#define NETLINK_LIST_MEMBERSHIPS 9 #define NETLINK_LIST_MEMBERSHIPS 9
#define NETLINK_CAP_ACK 10 #define NETLINK_CAP_ACK 10
#define NETLINK_EXT_ACK 11 #define NETLINK_EXT_ACK 11
#define NETLINK_DUMP_STRICT_CHK 12
struct nl_pktinfo { struct nl_pktinfo {
__u32 group; __u32 group;

View File

@ -646,10 +646,12 @@ struct perf_event_mmap_page {
* *
* PERF_RECORD_MISC_MMAP_DATA - PERF_RECORD_MMAP* events * PERF_RECORD_MISC_MMAP_DATA - PERF_RECORD_MMAP* events
* PERF_RECORD_MISC_COMM_EXEC - PERF_RECORD_COMM event * PERF_RECORD_MISC_COMM_EXEC - PERF_RECORD_COMM event
* PERF_RECORD_MISC_FORK_EXEC - PERF_RECORD_FORK event (perf internal)
* PERF_RECORD_MISC_SWITCH_OUT - PERF_RECORD_SWITCH* events * PERF_RECORD_MISC_SWITCH_OUT - PERF_RECORD_SWITCH* events
*/ */
#define PERF_RECORD_MISC_MMAP_DATA (1 << 13) #define PERF_RECORD_MISC_MMAP_DATA (1 << 13)
#define PERF_RECORD_MISC_COMM_EXEC (1 << 13) #define PERF_RECORD_MISC_COMM_EXEC (1 << 13)
#define PERF_RECORD_MISC_FORK_EXEC (1 << 13)
#define PERF_RECORD_MISC_SWITCH_OUT (1 << 13) #define PERF_RECORD_MISC_SWITCH_OUT (1 << 13)
/* /*
* These PERF_RECORD_MISC_* flags below are safely reused * These PERF_RECORD_MISC_* flags below are safely reused

View File

@ -752,7 +752,7 @@ struct snd_timer_info {
#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */ #define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */
struct snd_timer_params { struct snd_timer_params {
unsigned int flags; /* flags - SNDRV_MIXER_PSFLG_* */ unsigned int flags; /* flags - SNDRV_TIMER_PSFLG_* */
unsigned int ticks; /* requested resolution in ticks */ unsigned int ticks; /* requested resolution in ticks */
unsigned int queue_size; /* total size of queue (32-1024) */ unsigned int queue_size; /* total size of queue (32-1024) */
unsigned int reserved0; /* reserved, was: failure locations */ unsigned int reserved0; /* reserved, was: failure locations */

View File

@ -116,6 +116,7 @@ static int get_value(struct parse_opt_ctx_t *p,
case OPTION_INTEGER: case OPTION_INTEGER:
case OPTION_UINTEGER: case OPTION_UINTEGER:
case OPTION_LONG: case OPTION_LONG:
case OPTION_ULONG:
case OPTION_U64: case OPTION_U64:
default: default:
break; break;
@ -166,6 +167,7 @@ static int get_value(struct parse_opt_ctx_t *p,
case OPTION_INTEGER: case OPTION_INTEGER:
case OPTION_UINTEGER: case OPTION_UINTEGER:
case OPTION_LONG: case OPTION_LONG:
case OPTION_ULONG:
case OPTION_U64: case OPTION_U64:
default: default:
break; break;
@ -295,6 +297,22 @@ static int get_value(struct parse_opt_ctx_t *p,
return opterror(opt, "expects a numerical value", flags); return opterror(opt, "expects a numerical value", flags);
return 0; return 0;
case OPTION_ULONG:
if (unset) {
*(unsigned long *)opt->value = 0;
return 0;
}
if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
*(unsigned long *)opt->value = opt->defval;
return 0;
}
if (get_arg(p, opt, flags, &arg))
return -1;
*(unsigned long *)opt->value = strtoul(arg, (char **)&s, 10);
if (*s)
return opterror(opt, "expects a numerical value", flags);
return 0;
case OPTION_U64: case OPTION_U64:
if (unset) { if (unset) {
*(u64 *)opt->value = 0; *(u64 *)opt->value = 0;
@ -703,6 +721,7 @@ static void print_option_help(const struct option *opts, int full)
case OPTION_ARGUMENT: case OPTION_ARGUMENT:
break; break;
case OPTION_LONG: case OPTION_LONG:
case OPTION_ULONG:
case OPTION_U64: case OPTION_U64:
case OPTION_INTEGER: case OPTION_INTEGER:
case OPTION_UINTEGER: case OPTION_UINTEGER:

View File

@ -25,6 +25,7 @@ enum parse_opt_type {
OPTION_STRING, OPTION_STRING,
OPTION_INTEGER, OPTION_INTEGER,
OPTION_LONG, OPTION_LONG,
OPTION_ULONG,
OPTION_CALLBACK, OPTION_CALLBACK,
OPTION_U64, OPTION_U64,
OPTION_UINTEGER, OPTION_UINTEGER,
@ -133,6 +134,7 @@ struct option {
#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } #define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) }
#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) } #define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) }
#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } #define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
#define OPT_ULONG(s, l, v, h) { .type = OPTION_ULONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned long *), .help = (h) }
#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } #define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
#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) } #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) }
#define OPT_STRING_OPTARG(s, l, v, a, h, d) \ #define OPT_STRING_OPTARG(s, l, v, a, h, d) \

View File

@ -0,0 +1,19 @@
For --xed the xed tool is needed. Here is how to install it:
$ git clone https://github.com/intelxed/mbuild.git mbuild
$ git clone https://github.com/intelxed/xed
$ cd xed
$ ./mfile.py --share
$ ./mfile.py examples
$ sudo ./mfile.py --prefix=/usr/local install
$ sudo ldconfig
$ sudo cp obj/examples/xed /usr/local/bin
Basic xed testing:
$ xed | head -3
ERROR: required argument(s) were missing
Copyright (C) 2017, Intel Corporation. All rights reserved.
XED version: [v10.0-328-g7d62c8c49b7b]
$

View File

@ -106,7 +106,7 @@ in transaction, respectively.
While it is possible to create scripts to analyze the data, an alternative While it is possible to create scripts to analyze the data, an alternative
approach is available to export the data to a sqlite or postgresql database. approach is available to export the data to a sqlite or postgresql database.
Refer to script export-to-sqlite.py or export-to-postgresql.py for more details, Refer to script export-to-sqlite.py or export-to-postgresql.py for more details,
and to script call-graph-from-sql.py for an example of using the database. and to script exported-sql-viewer.py for an example of using the database.
There is also script intel-pt-events.py which provides an example of how to There is also script intel-pt-events.py which provides an example of how to
unpack the raw data for power events and PTWRITE. unpack the raw data for power events and PTWRITE.

View File

@ -11,10 +11,11 @@
l synthesize last branch entries (use with i or x) l synthesize last branch entries (use with i or x)
s skip initial number of events s skip initial number of events
The default is all events i.e. the same as --itrace=ibxwpe The default is all events i.e. the same as --itrace=ibxwpe,
except for perf script where it is --itrace=ce
In addition, the period (default 100000) for instructions events In addition, the period (default 100000, except for perf script where it is 1)
can be specified in units of: for instructions events can be specified in units of:
i instructions i instructions
t ticks t ticks

View File

@ -383,6 +383,24 @@ include::itrace.txt[]
will be printed. Each entry has function name and file/line. Enabled by will be printed. Each entry has function name and file/line. Enabled by
default, disable with --no-inline. default, disable with --no-inline.
--insn-trace::
Show instruction stream for intel_pt traces. Combine with --xed to
show disassembly.
--xed::
Run xed disassembler on output. Requires installing the xed disassembler.
--call-trace::
Show call stream for intel_pt traces. The CPUs are interleaved, but
can be filtered with -C.
--call-ret-trace::
Show call and return stream for intel_pt traces.
--graph-function::
For itrace only show specified functions and their callees for
itrace. Multiple functions can be separated by comma.
SEE ALSO SEE ALSO
-------- --------
linkperf:perf-record[1], linkperf:perf-script-perl[1], linkperf:perf-record[1], linkperf:perf-script-perl[1],

View File

@ -242,6 +242,16 @@ Default is to monitor all CPUS.
--hierarchy:: --hierarchy::
Enable hierarchy output. Enable hierarchy output.
--overwrite::
Enable this to use just the most recent records, which helps in high core count
machines such as Knights Landing/Mill, but right now is disabled by default as
the pausing used in this technique is leading to loss of metadata events such
as PERF_RECORD_MMAP which makes 'perf top' unable to resolve samples, leading
to lots of unknown samples appearing on the UI. Enable this if you are in such
machines and profiling a workload that doesn't creates short lived threads and/or
doesn't uses many executable mmap operations. Work is being planed to solve
this situation, till then, this will remain disabled by default.
--force:: --force::
Don't do ownership validation. Don't do ownership validation.

View File

@ -171,6 +171,11 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
--kernel-syscall-graph:: --kernel-syscall-graph::
Show the kernel callchains on the syscall exit path. Show the kernel callchains on the syscall exit path.
--max-events=N::
Stop after processing N events. Note that strace-like events are considered
only at exit time or when a syscall is interrupted, i.e. in those cases this
option is equivalent to the number of lines printed.
--max-stack:: --max-stack::
Set the stack depth limit when parsing the callchain, anything Set the stack depth limit when parsing the callchain, anything
beyond the specified depth will be ignored. Note that at this point beyond the specified depth will be ignored. Note that at this point
@ -238,6 +243,68 @@ Trace syscalls, major and minor pagefaults:
As you can see, there was major pagefault in python process, from As you can see, there was major pagefault in python process, from
CRYPTO_push_info_ routine which faulted somewhere in libcrypto.so. CRYPTO_push_info_ routine which faulted somewhere in libcrypto.so.
Trace the first 4 open, openat or open_by_handle_at syscalls (in the future more syscalls may match here):
$ perf trace -e open* --max-events 4
[root@jouet perf]# trace -e open* --max-events 4
2272.992 ( 0.037 ms): gnome-shell/1370 openat(dfd: CWD, filename: /proc/self/stat) = 31
2277.481 ( 0.139 ms): gnome-shell/3039 openat(dfd: CWD, filename: /proc/self/stat) = 65
3026.398 ( 0.076 ms): gnome-shell/3039 openat(dfd: CWD, filename: /proc/self/stat) = 65
4294.665 ( 0.015 ms): sed/15879 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) = 3
$
Trace the first minor page fault when running a workload:
# perf trace -F min --max-stack=7 --max-events 1 sleep 1
0.000 ( 0.000 ms): sleep/18006 minfault [__clear_user+0x1a] => 0x5626efa56080 (?k)
__clear_user ([kernel.kallsyms])
load_elf_binary ([kernel.kallsyms])
search_binary_handler ([kernel.kallsyms])
__do_execve_file.isra.33 ([kernel.kallsyms])
__x64_sys_execve ([kernel.kallsyms])
do_syscall_64 ([kernel.kallsyms])
entry_SYSCALL_64 ([kernel.kallsyms])
#
Trace the next min page page fault to take place on the first CPU:
# perf trace -F min --call-graph=dwarf --max-events 1 --cpu 0
0.000 ( 0.000 ms): Web Content/17136 minfault [js::gc::Chunk::fetchNextDecommittedArena+0x4b] => 0x7fbe6181b000 (?.)
js::gc::FreeSpan::initAsEmpty (inlined)
js::gc::Arena::setAsNotAllocated (inlined)
js::gc::Chunk::fetchNextDecommittedArena (/usr/lib64/firefox/libxul.so)
js::gc::Chunk::allocateArena (/usr/lib64/firefox/libxul.so)
js::gc::GCRuntime::allocateArena (/usr/lib64/firefox/libxul.so)
js::gc::ArenaLists::allocateFromArena (/usr/lib64/firefox/libxul.so)
js::gc::GCRuntime::tryNewTenuredThing<JSString, (js::AllowGC)1> (inlined)
js::AllocateString<JSString, (js::AllowGC)1> (/usr/lib64/firefox/libxul.so)
js::Allocate<JSThinInlineString, (js::AllowGC)1> (inlined)
JSThinInlineString::new_<(js::AllowGC)1> (inlined)
AllocateInlineString<(js::AllowGC)1, unsigned char> (inlined)
js::ConcatStrings<(js::AllowGC)1> (/usr/lib64/firefox/libxul.so)
[0x18b26e6bc2bd] (/tmp/perf-17136.map)
#
Trace the next two sched:sched_switch events, four block:*_plug events, the
next block:*_unplug and the next three net:*dev_queue events, this last one
with a backtrace of at most 16 entries, system wide:
# perf trace -e sched:*switch/nr=2/,block:*_plug/nr=4/,block:*_unplug/nr=1/,net:*dev_queue/nr=3,max-stack=16/
0.000 :0/0 sched:sched_switch:swapper/2:0 [120] S ==> rcu_sched:10 [120]
0.015 rcu_sched/10 sched:sched_switch:rcu_sched:10 [120] R ==> swapper/2:0 [120]
254.198 irq/50-iwlwifi/680 net:net_dev_queue:dev=wlp3s0 skbaddr=0xffff93498051f600 len=66
__dev_queue_xmit ([kernel.kallsyms])
273.977 :0/0 net:net_dev_queue:dev=wlp3s0 skbaddr=0xffff93498051f600 len=78
__dev_queue_xmit ([kernel.kallsyms])
274.007 :0/0 net:net_dev_queue:dev=wlp3s0 skbaddr=0xffff93498051ff00 len=78
__dev_queue_xmit ([kernel.kallsyms])
2930.140 kworker/u16:58/2722 block:block_plug:[kworker/u16:58]
2930.162 kworker/u16:58/2722 block:block_unplug:[kworker/u16:58] 1
4466.094 jbd2/dm-2-8/748 block:block_plug:[jbd2/dm-2-8]
8050.123 kworker/u16:30/2694 block:block_plug:[kworker/u16:30]
8050.271 kworker/u16:30/2694 block:block_plug:[kworker/u16:30]
#
SEE ALSO SEE ALSO
-------- --------
linkperf:perf-record[1], linkperf:perf-script[1] linkperf:perf-record[1], linkperf:perf-script[1]

View File

@ -1,4 +1,5 @@
include ../scripts/Makefile.include include ../scripts/Makefile.include
include ../scripts/Makefile.arch
# The default target of this Makefile is... # The default target of this Makefile is...
all: all:
@ -385,6 +386,8 @@ export INSTALL SHELL_PATH
SHELL = $(SHELL_PATH) SHELL = $(SHELL_PATH)
linux_uapi_dir := $(srctree)/tools/include/uapi/linux linux_uapi_dir := $(srctree)/tools/include/uapi/linux
asm_generic_uapi_dir := $(srctree)/tools/include/uapi/asm-generic
arch_asm_uapi_dir := $(srctree)/tools/arch/$(ARCH)/include/uapi/asm/
beauty_outdir := $(OUTPUT)trace/beauty/generated beauty_outdir := $(OUTPUT)trace/beauty/generated
beauty_ioctl_outdir := $(beauty_outdir)/ioctl beauty_ioctl_outdir := $(beauty_outdir)/ioctl
@ -460,6 +463,18 @@ madvise_behavior_tbl := $(srctree)/tools/perf/trace/beauty/madvise_behavior.sh
$(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl) $(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl)
$(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@ $(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@
mmap_flags_array := $(beauty_outdir)/mmap_flags_array.c
mmap_flags_tbl := $(srctree)/tools/perf/trace/beauty/mmap_flags.sh
$(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)
$(Q)$(SHELL) '$(mmap_flags_tbl)' $(asm_generic_uapi_dir) $(arch_asm_uapi_dir) > $@
mount_flags_array := $(beauty_outdir)/mount_flags_array.c
mount_flags_tbl := $(srctree)/tools/perf/trace/beauty/mount_flags.sh
$(mount_flags_array): $(linux_uapi_dir)/fs.h $(mount_flags_tbl)
$(Q)$(SHELL) '$(mount_flags_tbl)' $(linux_uapi_dir) > $@
prctl_option_array := $(beauty_outdir)/prctl_option_array.c prctl_option_array := $(beauty_outdir)/prctl_option_array.c
prctl_hdr_dir := $(srctree)/tools/include/uapi/linux/ prctl_hdr_dir := $(srctree)/tools/include/uapi/linux/
prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh prctl_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
$(socket_ipproto_array) \ $(socket_ipproto_array) \
$(vhost_virtio_ioctl_array) \ $(vhost_virtio_ioctl_array) \
$(madvise_behavior_array) \ $(madvise_behavior_array) \
$(mmap_flags_array) \
$(mount_flags_array) \
$(perf_ioctl_array) \ $(perf_ioctl_array) \
$(prctl_option_array) \ $(prctl_option_array) \
$(arch_errno_name_array) $(arch_errno_name_array)
@ -863,6 +880,8 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
$(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \ $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
$(OUTPUT)pmu-events/pmu-events.c \ $(OUTPUT)pmu-events/pmu-events.c \
$(OUTPUT)$(madvise_behavior_array) \ $(OUTPUT)$(madvise_behavior_array) \
$(OUTPUT)$(mmap_flags_array) \
$(OUTPUT)$(mount_flags_array) \
$(OUTPUT)$(drm_ioctl_array) \ $(OUTPUT)$(drm_ioctl_array) \
$(OUTPUT)$(pkey_alloc_access_rights_array) \ $(OUTPUT)$(pkey_alloc_access_rights_array) \
$(OUTPUT)$(sndrv_ctl_ioctl_array) \ $(OUTPUT)$(sndrv_ctl_ioctl_array) \

View File

@ -23,7 +23,7 @@ create_table_from_c()
{ {
local sc nr last_sc local sc nr last_sc
create_table_exe=`mktemp /tmp/create-table-XXXXXX` create_table_exe=`mktemp ${TMPDIR:-/tmp}/create-table-XXXXXX`
{ {

View File

@ -1,3 +1,5 @@
ifndef NO_DWARF ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1 PERF_HAVE_DWARF_REGS := 1
endif endif
PERF_HAVE_JITDUMP := 1

View File

@ -0,0 +1,169 @@
// SPDX-License-Identifier: GPL-2.0
static int is_branch_cond(const char *cond)
{
if (cond[0] == '\0')
return 1;
if (cond[0] == 'a' && cond[1] == '\0')
return 1;
if (cond[0] == 'c' &&
(cond[1] == 'c' || cond[1] == 's') &&
cond[2] == '\0')
return 1;
if (cond[0] == 'e' &&
(cond[1] == '\0' ||
(cond[1] == 'q' && cond[2] == '\0')))
return 1;
if (cond[0] == 'g' &&
(cond[1] == '\0' ||
(cond[1] == 't' && cond[2] == '\0') ||
(cond[1] == 'e' && cond[2] == '\0') ||
(cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
return 1;
if (cond[0] == 'l' &&
(cond[1] == '\0' ||
(cond[1] == 't' && cond[2] == '\0') ||
(cond[1] == 'u' && cond[2] == '\0') ||
(cond[1] == 'e' && cond[2] == '\0') ||
(cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
return 1;
if (cond[0] == 'n' &&
(cond[1] == '\0' ||
(cond[1] == 'e' && cond[2] == '\0') ||
(cond[1] == 'z' && cond[2] == '\0') ||
(cond[1] == 'e' && cond[2] == 'g' && cond[3] == '\0')))
return 1;
if (cond[0] == 'b' &&
cond[1] == 'p' &&
cond[2] == 'o' &&
cond[3] == 's' &&
cond[4] == '\0')
return 1;
if (cond[0] == 'v' &&
(cond[1] == 'c' || cond[1] == 's') &&
cond[2] == '\0')
return 1;
if (cond[0] == 'b' &&
cond[1] == 'z' &&
cond[2] == '\0')
return 1;
return 0;
}
static int is_branch_reg_cond(const char *cond)
{
if ((cond[0] == 'n' || cond[0] == 'l') &&
cond[1] == 'z' &&
cond[2] == '\0')
return 1;
if (cond[0] == 'z' &&
cond[1] == '\0')
return 1;
if ((cond[0] == 'g' || cond[0] == 'l') &&
cond[1] == 'e' &&
cond[2] == 'z' &&
cond[3] == '\0')
return 1;
if (cond[0] == 'g' &&
cond[1] == 'z' &&
cond[2] == '\0')
return 1;
return 0;
}
static int is_branch_float_cond(const char *cond)
{
if (cond[0] == '\0')
return 1;
if ((cond[0] == 'a' || cond[0] == 'e' ||
cond[0] == 'z' || cond[0] == 'g' ||
cond[0] == 'l' || cond[0] == 'n' ||
cond[0] == 'o' || cond[0] == 'u') &&
cond[1] == '\0')
return 1;
if (((cond[0] == 'g' && cond[1] == 'e') ||
(cond[0] == 'l' && (cond[1] == 'e' ||
cond[1] == 'g')) ||
(cond[0] == 'n' && (cond[1] == 'e' ||
cond[1] == 'z')) ||
(cond[0] == 'u' && (cond[1] == 'e' ||
cond[1] == 'g' ||
cond[1] == 'l'))) &&
cond[2] == '\0')
return 1;
if (cond[0] == 'u' &&
(cond[1] == 'g' || cond[1] == 'l') &&
cond[2] == 'e' &&
cond[3] == '\0')
return 1;
return 0;
}
static struct ins_ops *sparc__associate_instruction_ops(struct arch *arch, const char *name)
{
struct ins_ops *ops = NULL;
if (!strcmp(name, "call") ||
!strcmp(name, "jmp") ||
!strcmp(name, "jmpl")) {
ops = &call_ops;
} else if (!strcmp(name, "ret") ||
!strcmp(name, "retl") ||
!strcmp(name, "return")) {
ops = &ret_ops;
} else if (!strcmp(name, "mov")) {
ops = &mov_ops;
} else {
if (name[0] == 'c' &&
(name[1] == 'w' || name[1] == 'x'))
name += 2;
if (name[0] == 'b') {
const char *cond = name + 1;
if (cond[0] == 'r') {
if (is_branch_reg_cond(cond + 1))
ops = &jump_ops;
} else if (is_branch_cond(cond)) {
ops = &jump_ops;
}
} else if (name[0] == 'f' && name[1] == 'b') {
if (is_branch_float_cond(name + 2))
ops = &jump_ops;
}
}
if (ops)
arch__associate_ins_ops(arch, name, ops);
return ops;
}
static int sparc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
{
if (!arch->initialized) {
arch->initialized = true;
arch->associate_instruction_ops = sparc__associate_instruction_ops;
arch->objdump.comment_char = '#';
}
return 0;
}

View File

@ -592,6 +592,9 @@ static void record__init_features(struct record *rec)
if (!rec->opts.full_auxtrace) if (!rec->opts.full_auxtrace)
perf_header__clear_feat(&session->header, HEADER_AUXTRACE); perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns))
perf_header__clear_feat(&session->header, HEADER_CLOCKID);
perf_header__clear_feat(&session->header, HEADER_STAT); perf_header__clear_feat(&session->header, HEADER_STAT);
} }
@ -897,6 +900,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
record__init_features(rec); record__init_features(rec);
if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
if (forks) { if (forks) {
err = perf_evlist__prepare_workload(rec->evlist, &opts->target, err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
argv, data->is_pipe, argv, data->is_pipe,
@ -1337,6 +1343,19 @@ static const struct clockid_map clockids[] = {
CLOCKID_END, CLOCKID_END,
}; };
static int get_clockid_res(clockid_t clk_id, u64 *res_ns)
{
struct timespec res;
*res_ns = 0;
if (!clock_getres(clk_id, &res))
*res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
else
pr_warning("WARNING: Failed to determine specified clock resolution.\n");
return 0;
}
static int parse_clockid(const struct option *opt, const char *str, int unset) static int parse_clockid(const struct option *opt, const char *str, int unset)
{ {
struct record_opts *opts = (struct record_opts *)opt->value; 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)
/* if its a number, we're done */ /* if its a number, we're done */
if (sscanf(str, "%d", &opts->clockid) == 1) if (sscanf(str, "%d", &opts->clockid) == 1)
return 0; return get_clockid_res(opts->clockid, &opts->clockid_res_ns);
/* allow a "CLOCK_" prefix to the name */ /* allow a "CLOCK_" prefix to the name */
if (!strncasecmp(str, "CLOCK_", 6)) if (!strncasecmp(str, "CLOCK_", 6))
@ -1369,7 +1388,8 @@ static int parse_clockid(const struct option *opt, const char *str, int unset)
for (cm = clockids; cm->name; cm++) { for (cm = clockids; cm->name; cm++) {
if (!strcasecmp(str, cm->name)) { if (!strcasecmp(str, cm->name)) {
opts->clockid = cm->clockid; opts->clockid = cm->clockid;
return 0; return get_clockid_res(opts->clockid,
&opts->clockid_res_ns);
} }
} }

View File

@ -44,6 +44,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <subcmd/pager.h>
#include "sane_ctype.h" #include "sane_ctype.h"
@ -912,7 +913,7 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,
static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en, static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
struct perf_insn *x, u8 *inbuf, int len, struct perf_insn *x, u8 *inbuf, int len,
int insn, FILE *fp) int insn, FILE *fp, int *total_cycles)
{ {
int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", ip, int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", ip,
dump_insn(x, ip, inbuf, len, NULL), dump_insn(x, ip, inbuf, len, NULL),
@ -921,7 +922,8 @@ static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
en->flags.in_tx ? " INTX" : "", en->flags.in_tx ? " INTX" : "",
en->flags.abort ? " ABORT" : ""); en->flags.abort ? " ABORT" : "");
if (en->flags.cycles) { if (en->flags.cycles) {
printed += fprintf(fp, " %d cycles", en->flags.cycles); *total_cycles += en->flags.cycles;
printed += fprintf(fp, " %d cycles [%d]", en->flags.cycles, *total_cycles);
if (insn) if (insn)
printed += fprintf(fp, " %.2f IPC", (float)insn / en->flags.cycles); printed += fprintf(fp, " %.2f IPC", (float)insn / en->flags.cycles);
} }
@ -978,6 +980,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
u8 buffer[MAXBB]; u8 buffer[MAXBB];
unsigned off; unsigned off;
struct symbol *lastsym = NULL; struct symbol *lastsym = NULL;
int total_cycles = 0;
if (!(br && br->nr)) if (!(br && br->nr))
return 0; return 0;
@ -998,7 +1001,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
printed += ip__fprintf_sym(br->entries[nr - 1].from, thread, printed += ip__fprintf_sym(br->entries[nr - 1].from, thread,
x.cpumode, x.cpu, &lastsym, attr, fp); x.cpumode, x.cpu, &lastsym, attr, fp);
printed += ip__fprintf_jump(br->entries[nr - 1].from, &br->entries[nr - 1], printed += ip__fprintf_jump(br->entries[nr - 1].from, &br->entries[nr - 1],
&x, buffer, len, 0, fp); &x, buffer, len, 0, fp, &total_cycles);
} }
/* Print all blocks */ /* Print all blocks */
@ -1026,7 +1029,8 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp); printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
if (ip == end) { if (ip == end) {
printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp); printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp,
&total_cycles);
break; break;
} else { } else {
printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip, printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip,
@ -1104,6 +1108,35 @@ out:
return printed; return printed;
} }
static const char *resolve_branch_sym(struct perf_sample *sample,
struct perf_evsel *evsel,
struct thread *thread,
struct addr_location *al,
u64 *ip)
{
struct addr_location addr_al;
struct perf_event_attr *attr = &evsel->attr;
const char *name = NULL;
if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
if (sample_addr_correlates_sym(attr)) {
thread__resolve(thread, &addr_al, sample);
if (addr_al.sym)
name = addr_al.sym->name;
else
*ip = sample->addr;
} else {
*ip = sample->addr;
}
} else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
if (al->sym)
name = al->sym->name;
else
*ip = sample->ip;
}
return name;
}
static int perf_sample__fprintf_callindent(struct perf_sample *sample, static int perf_sample__fprintf_callindent(struct perf_sample *sample,
struct perf_evsel *evsel, struct perf_evsel *evsel,
struct thread *thread, struct thread *thread,
@ -1111,7 +1144,6 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
{ {
struct perf_event_attr *attr = &evsel->attr; struct perf_event_attr *attr = &evsel->attr;
size_t depth = thread_stack__depth(thread); size_t depth = thread_stack__depth(thread);
struct addr_location addr_al;
const char *name = NULL; const char *name = NULL;
static int spacing; static int spacing;
int len = 0; int len = 0;
@ -1125,22 +1157,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN) if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN)
depth += 1; depth += 1;
if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) { name = resolve_branch_sym(sample, evsel, thread, al, &ip);
if (sample_addr_correlates_sym(attr)) {
thread__resolve(thread, &addr_al, sample);
if (addr_al.sym)
name = addr_al.sym->name;
else
ip = sample->addr;
} else {
ip = sample->addr;
}
} else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
if (al->sym)
name = al->sym->name;
else
ip = sample->ip;
}
if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) { if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) {
dlen += fprintf(fp, "("); dlen += fprintf(fp, "(");
@ -1646,6 +1663,47 @@ static void perf_sample__fprint_metric(struct perf_script *script,
} }
} }
static bool show_event(struct perf_sample *sample,
struct perf_evsel *evsel,
struct thread *thread,
struct addr_location *al)
{
int depth = thread_stack__depth(thread);
if (!symbol_conf.graph_function)
return true;
if (thread->filter) {
if (depth <= thread->filter_entry_depth) {
thread->filter = false;
return false;
}
return true;
} else {
const char *s = symbol_conf.graph_function;
u64 ip;
const char *name = resolve_branch_sym(sample, evsel, thread, al,
&ip);
unsigned nlen;
if (!name)
return false;
nlen = strlen(name);
while (*s) {
unsigned len = strcspn(s, ",");
if (nlen == len && !strncmp(name, s, len)) {
thread->filter = true;
thread->filter_entry_depth = depth;
return true;
}
s += len;
if (*s == ',')
s++;
}
return false;
}
}
static void process_event(struct perf_script *script, static void process_event(struct perf_script *script,
struct perf_sample *sample, struct perf_evsel *evsel, struct perf_sample *sample, struct perf_evsel *evsel,
struct addr_location *al, struct addr_location *al,
@ -1660,6 +1718,9 @@ static void process_event(struct perf_script *script,
if (output[type].fields == 0) if (output[type].fields == 0)
return; return;
if (!show_event(sample, evsel, thread, al))
return;
++es->samples; ++es->samples;
perf_sample__fprintf_start(sample, thread, evsel, perf_sample__fprintf_start(sample, thread, evsel,
@ -1737,6 +1798,9 @@ static void process_event(struct perf_script *script,
if (PRINT_FIELD(METRIC)) if (PRINT_FIELD(METRIC))
perf_sample__fprint_metric(script, thread, evsel, sample, fp); perf_sample__fprint_metric(script, thread, evsel, sample, fp);
if (verbose)
fflush(fp);
} }
static struct scripting_ops *scripting_ops; static struct scripting_ops *scripting_ops;
@ -3100,6 +3164,44 @@ static int perf_script__process_auxtrace_info(struct perf_session *session,
#define perf_script__process_auxtrace_info 0 #define perf_script__process_auxtrace_info 0
#endif #endif
static int parse_insn_trace(const struct option *opt __maybe_unused,
const char *str __maybe_unused,
int unset __maybe_unused)
{
parse_output_fields(NULL, "+insn,-event,-period", 0);
itrace_parse_synth_opts(opt, "i0ns", 0);
nanosecs = true;
return 0;
}
static int parse_xed(const struct option *opt __maybe_unused,
const char *str __maybe_unused,
int unset __maybe_unused)
{
force_pager("xed -F insn: -A -64 | less");
return 0;
}
static int parse_call_trace(const struct option *opt __maybe_unused,
const char *str __maybe_unused,
int unset __maybe_unused)
{
parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent", 0);
itrace_parse_synth_opts(opt, "cewp", 0);
nanosecs = true;
return 0;
}
static int parse_callret_trace(const struct option *opt __maybe_unused,
const char *str __maybe_unused,
int unset __maybe_unused)
{
parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent,+flags", 0);
itrace_parse_synth_opts(opt, "crewp", 0);
nanosecs = true;
return 0;
}
int cmd_script(int argc, const char **argv) int cmd_script(int argc, const char **argv)
{ {
bool show_full_info = false; bool show_full_info = false;
@ -3109,7 +3211,10 @@ int cmd_script(int argc, const char **argv)
char *rec_script_path = NULL; char *rec_script_path = NULL;
char *rep_script_path = NULL; char *rep_script_path = NULL;
struct perf_session *session; struct perf_session *session;
struct itrace_synth_opts itrace_synth_opts = { .set = false, }; struct itrace_synth_opts itrace_synth_opts = {
.set = false,
.default_no_sample = true,
};
char *script_path = NULL; char *script_path = NULL;
const char **__argv; const char **__argv;
int i, j, err = 0; int i, j, err = 0;
@ -3184,6 +3289,16 @@ int cmd_script(int argc, const char **argv)
"system-wide collection from all CPUs"), "system-wide collection from all CPUs"),
OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
"only consider these symbols"), "only consider these symbols"),
OPT_CALLBACK_OPTARG(0, "insn-trace", &itrace_synth_opts, NULL, NULL,
"Decode instructions from itrace", parse_insn_trace),
OPT_CALLBACK_OPTARG(0, "xed", NULL, NULL, NULL,
"Run xed disassembler on output", parse_xed),
OPT_CALLBACK_OPTARG(0, "call-trace", &itrace_synth_opts, NULL, NULL,
"Decode calls from from itrace", parse_call_trace),
OPT_CALLBACK_OPTARG(0, "call-ret-trace", &itrace_synth_opts, NULL, NULL,
"Decode calls and returns from itrace", parse_callret_trace),
OPT_STRING(0, "graph-function", &symbol_conf.graph_function, "symbol[,symbol...]",
"Only print symbols and callees with --call-trace/--call-ret-trace"),
OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]", OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]",
"Stop display of callgraph at these symbols"), "Stop display of callgraph at these symbols"),
OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
@ -3417,8 +3532,10 @@ int cmd_script(int argc, const char **argv)
exit(-1); exit(-1);
} }
if (!script_name) if (!script_name) {
setup_pager(); setup_pager();
use_browser = 0;
}
session = perf_session__new(&data, false, &script.tool); session = perf_session__new(&data, false, &script.tool);
if (session == NULL) if (session == NULL)
@ -3439,7 +3556,8 @@ int cmd_script(int argc, const char **argv)
script.session = session; script.session = session;
script__setup_sample_type(&script); script__setup_sample_type(&script);
if (output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) if ((output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) ||
symbol_conf.graph_function)
itrace_synth_opts.thread_stack = true; itrace_synth_opts.thread_stack = true;
session->itrace_synth_opts = &itrace_synth_opts; session->itrace_synth_opts = &itrace_synth_opts;

View File

@ -409,6 +409,28 @@ static struct perf_evsel *perf_evsel__reset_weak_group(struct perf_evsel *evsel)
return leader; return leader;
} }
static bool is_target_alive(struct target *_target,
struct thread_map *threads)
{
struct stat st;
int i;
if (!target__has_task(_target))
return true;
for (i = 0; i < threads->nr; i++) {
char path[PATH_MAX];
scnprintf(path, PATH_MAX, "%s/%d", procfs__mountpoint(),
threads->map[i].pid);
if (!stat(path, &st))
return true;
}
return false;
}
static int __run_perf_stat(int argc, const char **argv, int run_idx) static int __run_perf_stat(int argc, const char **argv, int run_idx)
{ {
int interval = stat_config.interval; int interval = stat_config.interval;
@ -579,6 +601,8 @@ try_again:
enable_counters(); enable_counters();
while (!done) { while (!done) {
nanosleep(&ts, NULL); nanosleep(&ts, NULL);
if (!is_target_alive(&target, evsel_list->threads))
break;
if (timeout) if (timeout)
break; break;
if (interval) { if (interval) {

View File

@ -1134,11 +1134,6 @@ static int __cmd_top(struct perf_top *top)
if (!target__none(&opts->target)) if (!target__none(&opts->target))
perf_evlist__enable(top->evlist); perf_evlist__enable(top->evlist);
/* Wait for a minimal set of events before starting the snapshot */
perf_evlist__poll(top->evlist, 100);
perf_top__mmap_read(top);
ret = -1; ret = -1;
if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
display_thread), top)) { display_thread), top)) {
@ -1156,6 +1151,11 @@ static int __cmd_top(struct perf_top *top)
} }
} }
/* Wait for a minimal set of events before starting the snapshot */
perf_evlist__poll(top->evlist, 100);
perf_top__mmap_read(top);
while (!done) { while (!done) {
u64 hits = top->samples; u64 hits = top->samples;
@ -1257,7 +1257,14 @@ int cmd_top(int argc, const char **argv)
.uses_mmap = true, .uses_mmap = true,
}, },
.proc_map_timeout = 500, .proc_map_timeout = 500,
.overwrite = 1, /*
* FIXME: This will lose PERF_RECORD_MMAP and other metadata
* when we pause, fix that and reenable. Probably using a
* separate evlist with a dummy event, i.e. a non-overwrite
* ring buffer just for metadata events, while PERF_RECORD_SAMPLE
* stays in overwrite mode. -acme
* */
.overwrite = 0,
}, },
.max_stack = sysctl__max_stack(), .max_stack = sysctl__max_stack(),
.annotation_opts = annotation__default_options, .annotation_opts = annotation__default_options,
@ -1372,6 +1379,8 @@ int cmd_top(int argc, const char **argv)
"Show raw trace event output (do not use print fmt or plugins)"), "Show raw trace event output (do not use print fmt or plugins)"),
OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy, OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
"Show entries in a hierarchy"), "Show entries in a hierarchy"),
OPT_BOOLEAN(0, "overwrite", &top.record_opts.overwrite,
"Use a backward ring buffer, default: no"),
OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"), OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"),
OPT_UINTEGER(0, "num-thread-synthesize", &top.nr_threads_synthesize, OPT_UINTEGER(0, "num-thread-synthesize", &top.nr_threads_synthesize,
"number of thread to run event synthesize"), "number of thread to run event synthesize"),

View File

@ -89,6 +89,8 @@ struct trace {
u64 base_time; u64 base_time;
FILE *output; FILE *output;
unsigned long nr_events; unsigned long nr_events;
unsigned long nr_events_printed;
unsigned long max_events;
struct strlist *ev_qualifier; struct strlist *ev_qualifier;
struct { struct {
size_t nr; size_t nr;
@ -612,6 +614,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
struct syscall_arg_fmt { struct syscall_arg_fmt {
size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg); size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
unsigned long (*mask_val)(struct syscall_arg *arg, unsigned long val);
void *parm; void *parm;
const char *name; const char *name;
bool show_zero; bool show_zero;
@ -723,6 +726,10 @@ static struct syscall_fmt {
.arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
[2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
[3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, }, [3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, },
{ .name = "mount",
.arg = { [0] = { .scnprintf = SCA_FILENAME, /* dev_name */ },
[3] = { .scnprintf = SCA_MOUNT_FLAGS, /* flags */
.mask_val = SCAMV_MOUNT_FLAGS, /* flags */ }, }, },
{ .name = "mprotect", { .name = "mprotect",
.arg = { [0] = { .scnprintf = SCA_HEX, /* start */ }, .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
[2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, }, [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, },
@ -832,7 +839,8 @@ static struct syscall_fmt {
.arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
{ .name = "tkill", { .name = "tkill",
.arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
{ .name = "umount2", .alias = "umount", }, { .name = "umount2", .alias = "umount",
.arg = { [0] = { .scnprintf = SCA_FILENAME, /* name */ }, }, },
{ .name = "uname", .alias = "newuname", }, { .name = "uname", .alias = "newuname", },
{ .name = "unlinkat", { .name = "unlinkat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
@ -856,6 +864,18 @@ static struct syscall_fmt *syscall_fmt__find(const char *name)
return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp); return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
} }
static struct syscall_fmt *syscall_fmt__find_by_alias(const char *alias)
{
int i, nmemb = ARRAY_SIZE(syscall_fmts);
for (i = 0; i < nmemb; ++i) {
if (syscall_fmts[i].alias && strcmp(syscall_fmts[i].alias, alias) == 0)
return &syscall_fmts[i];
}
return NULL;
}
/* /*
* is_exit: is this "exit" or "exit_group"? * is_exit: is this "exit" or "exit_group"?
* is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter. * 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,
return scnprintf(bf, size, "arg%d: ", arg->idx); return scnprintf(bf, size, "arg%d: ", arg->idx);
} }
/*
* Check if the value is in fact zero, i.e. mask whatever needs masking, such
* as mount 'flags' argument that needs ignoring some magic flag, see comment
* in tools/perf/trace/beauty/mount_flags.c
*/
static unsigned long syscall__mask_val(struct syscall *sc, struct syscall_arg *arg, unsigned long val)
{
if (sc->arg_fmt && sc->arg_fmt[arg->idx].mask_val)
return sc->arg_fmt[arg->idx].mask_val(arg, val);
return val;
}
static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size, static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size,
struct syscall_arg *arg, unsigned long val) struct syscall_arg *arg, unsigned long val)
{ {
@ -1533,6 +1566,11 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
continue; continue;
val = syscall_arg__val(&arg, arg.idx); val = syscall_arg__val(&arg, arg.idx);
/*
* Some syscall args need some mask, most don't and
* return val untouched.
*/
val = syscall__mask_val(sc, &arg, val);
/* /*
* Suppress this argument if its value is zero and * Suppress this argument if its value is zero and
@ -1664,6 +1702,8 @@ static int trace__printf_interrupted_entry(struct trace *trace)
printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str); printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
ttrace->entry_pending = false; ttrace->entry_pending = false;
++trace->nr_events_printed;
return printed; return printed;
} }
@ -1810,12 +1850,14 @@ static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evse
int max_stack = evsel->attr.sample_max_stack ? int max_stack = evsel->attr.sample_max_stack ?
evsel->attr.sample_max_stack : evsel->attr.sample_max_stack :
trace->max_stack; trace->max_stack;
int err;
if (machine__resolve(trace->host, &al, sample) < 0 || if (machine__resolve(trace->host, &al, sample) < 0)
thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, max_stack))
return -1; return -1;
return 0; err = thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, max_stack);
addr_location__put(&al);
return err;
} }
static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample) static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
@ -1940,6 +1982,13 @@ errno_print: {
fputc('\n', trace->output); fputc('\n', trace->output);
/*
* We only consider an 'event' for the sake of --max-events a non-filtered
* sys_enter + sys_exit and other tracepoint events.
*/
if (++trace->nr_events_printed == trace->max_events && trace->max_events != ULONG_MAX)
interrupted = true;
if (callchain_ret > 0) if (callchain_ret > 0)
trace__fprintf_callchain(trace, sample); trace__fprintf_callchain(trace, sample);
else if (callchain_ret < 0) else if (callchain_ret < 0)
@ -2072,14 +2121,25 @@ static void bpf_output__fprintf(struct trace *trace,
{ {
binary__fprintf(sample->raw_data, sample->raw_size, 8, binary__fprintf(sample->raw_data, sample->raw_size, 8,
bpf_output__printer, NULL, trace->output); bpf_output__printer, NULL, trace->output);
++trace->nr_events_printed;
} }
static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
union perf_event *event __maybe_unused, union perf_event *event __maybe_unused,
struct perf_sample *sample) struct perf_sample *sample)
{ {
struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); struct thread *thread;
int callchain_ret = 0; int callchain_ret = 0;
/*
* Check if we called perf_evsel__disable(evsel) due to, for instance,
* this event's max_events having been hit and this is an entry coming
* from the ring buffer that we should discard, since the max events
* have already been considered/printed.
*/
if (evsel->disabled)
return 0;
thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
if (sample->callchain) { if (sample->callchain) {
callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor); 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,
event_format__fprintf(evsel->tp_format, sample->cpu, event_format__fprintf(evsel->tp_format, sample->cpu,
sample->raw_data, sample->raw_size, sample->raw_data, sample->raw_size,
trace->output); trace->output);
++trace->nr_events_printed;
if (evsel->max_events != ULONG_MAX && ++evsel->nr_events_printed == evsel->max_events) {
perf_evsel__disable(evsel);
perf_evsel__close(evsel);
}
} }
} }
@ -2137,8 +2203,8 @@ newline:
trace__fprintf_callchain(trace, sample); trace__fprintf_callchain(trace, sample);
else if (callchain_ret < 0) else if (callchain_ret < 0)
pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
thread__put(thread);
out: out:
thread__put(thread);
return 0; return 0;
} }
@ -2225,6 +2291,8 @@ static int trace__pgfault(struct trace *trace,
trace__fprintf_callchain(trace, sample); trace__fprintf_callchain(trace, sample);
else if (callchain_ret < 0) else if (callchain_ret < 0)
pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
++trace->nr_events_printed;
out: out:
err = 0; err = 0;
out_put: out_put:
@ -2402,6 +2470,9 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
tracepoint_handler handler = evsel->handler; tracepoint_handler handler = evsel->handler;
handler(trace, evsel, event, sample); handler(trace, evsel, event, sample);
} }
if (trace->nr_events_printed >= trace->max_events && trace->max_events != ULONG_MAX)
interrupted = true;
} }
static int trace__add_syscall_newtp(struct trace *trace) static int trace__add_syscall_newtp(struct trace *trace)
@ -2706,7 +2777,7 @@ next_event:
int timeout = done ? 100 : -1; int timeout = done ? 100 : -1;
if (!draining && perf_evlist__poll(evlist, timeout) > 0) { if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0) if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP | POLLNVAL) == 0)
draining = true; draining = true;
goto again; goto again;
@ -3138,6 +3209,7 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
int len = strlen(str) + 1, err = -1, list, idx; int len = strlen(str) + 1, err = -1, list, idx;
char *strace_groups_dir = system_path(STRACE_GROUPS_DIR); char *strace_groups_dir = system_path(STRACE_GROUPS_DIR);
char group_name[PATH_MAX]; char group_name[PATH_MAX];
struct syscall_fmt *fmt;
if (strace_groups_dir == NULL) if (strace_groups_dir == NULL)
return -1; return -1;
@ -3155,12 +3227,19 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
if (syscalltbl__id(trace->sctbl, s) >= 0 || if (syscalltbl__id(trace->sctbl, s) >= 0 ||
syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) { syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) {
list = 1; list = 1;
goto do_concat;
}
fmt = syscall_fmt__find_by_alias(s);
if (fmt != NULL) {
list = 1;
s = fmt->name;
} else { } else {
path__join(group_name, sizeof(group_name), strace_groups_dir, s); path__join(group_name, sizeof(group_name), strace_groups_dir, s);
if (access(group_name, R_OK) == 0) if (access(group_name, R_OK) == 0)
list = 1; list = 1;
} }
do_concat:
if (lists[list]) { if (lists[list]) {
sprintf(lists[list] + strlen(lists[list]), ",%s", s); sprintf(lists[list] + strlen(lists[list]), ",%s", s);
} else { } else {
@ -3249,6 +3328,7 @@ int cmd_trace(int argc, const char **argv)
.trace_syscalls = false, .trace_syscalls = false,
.kernel_syscallchains = false, .kernel_syscallchains = false,
.max_stack = UINT_MAX, .max_stack = UINT_MAX,
.max_events = ULONG_MAX,
}; };
const char *output_name = NULL; const char *output_name = NULL;
const struct option trace_options[] = { const struct option trace_options[] = {
@ -3301,6 +3381,8 @@ int cmd_trace(int argc, const char **argv)
&record_parse_callchain_opt), &record_parse_callchain_opt),
OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains, OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
"Show the kernel callchains on the syscall exit path"), "Show the kernel callchains on the syscall exit path"),
OPT_ULONG(0, "max-events", &trace.max_events,
"Set the maximum number of events to print, exit after that is reached. "),
OPT_UINTEGER(0, "min-stack", &trace.min_stack, OPT_UINTEGER(0, "min-stack", &trace.min_stack,
"Set the minimum stack depth when parsing the callchain, " "Set the minimum stack depth when parsing the callchain, "
"anything below the specified depth will be ignored."), "anything below the specified depth will be ignored."),

View File

@ -5,6 +5,7 @@ HEADERS='
include/uapi/drm/drm.h include/uapi/drm/drm.h
include/uapi/drm/i915_drm.h include/uapi/drm/i915_drm.h
include/uapi/linux/fcntl.h include/uapi/linux/fcntl.h
include/uapi/linux/fs.h
include/uapi/linux/kcmp.h include/uapi/linux/kcmp.h
include/uapi/linux/kvm.h include/uapi/linux/kvm.h
include/uapi/linux/in.h include/uapi/linux/in.h

View File

@ -81,6 +81,7 @@ struct record_opts {
unsigned initial_delay; unsigned initial_delay;
bool use_clockid; bool use_clockid;
clockid_t clockid; clockid_t clockid;
u64 clockid_res_ns;
unsigned int proc_map_timeout; unsigned int proc_map_timeout;
}; };

View File

@ -1,339 +0,0 @@
#!/usr/bin/python2
# call-graph-from-sql.py: create call-graph from sql database
# Copyright (c) 2014-2017, Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
# To use this script you will need to have exported data using either the
# export-to-sqlite.py or the export-to-postgresql.py script. Refer to those
# scripts for details.
#
# Following on from the example in the export scripts, a
# call-graph can be displayed for the pt_example database like this:
#
# python tools/perf/scripts/python/call-graph-from-sql.py pt_example
#
# Note that for PostgreSQL, this script supports connecting to remote databases
# by setting hostname, port, username, password, and dbname e.g.
#
# python tools/perf/scripts/python/call-graph-from-sql.py "hostname=myhost username=myuser password=mypassword dbname=pt_example"
#
# The result is a GUI window with a tree representing a context-sensitive
# call-graph. Expanding a couple of levels of the tree and adjusting column
# widths to suit will display something like:
#
# Call Graph: pt_example
# Call Path Object Count Time(ns) Time(%) Branch Count Branch Count(%)
# v- ls
# v- 2638:2638
# v- _start ld-2.19.so 1 10074071 100.0 211135 100.0
# |- unknown unknown 1 13198 0.1 1 0.0
# >- _dl_start ld-2.19.so 1 1400980 13.9 19637 9.3
# >- _d_linit_internal ld-2.19.so 1 448152 4.4 11094 5.3
# v-__libc_start_main@plt ls 1 8211741 81.5 180397 85.4
# >- _dl_fixup ld-2.19.so 1 7607 0.1 108 0.1
# >- __cxa_atexit libc-2.19.so 1 11737 0.1 10 0.0
# >- __libc_csu_init ls 1 10354 0.1 10 0.0
# |- _setjmp libc-2.19.so 1 0 0.0 4 0.0
# v- main ls 1 8182043 99.6 180254 99.9
#
# Points to note:
# The top level is a command name (comm)
# The next level is a thread (pid:tid)
# Subsequent levels are functions
# 'Count' is the number of calls
# 'Time' is the elapsed time until the function returns
# Percentages are relative to the level above
# 'Branch Count' is the total number of branches for that function and all
# functions that it calls
import sys
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtSql import *
from decimal import *
class TreeItem():
def __init__(self, db, row, parent_item):
self.db = db
self.row = row
self.parent_item = parent_item
self.query_done = False;
self.child_count = 0
self.child_items = []
self.data = ["", "", "", "", "", "", ""]
self.comm_id = 0
self.thread_id = 0
self.call_path_id = 1
self.branch_count = 0
self.time = 0
if not parent_item:
self.setUpRoot()
def setUpRoot(self):
self.query_done = True
query = QSqlQuery(self.db)
ret = query.exec_('SELECT id, comm FROM comms')
if not ret:
raise Exception("Query failed: " + query.lastError().text())
while query.next():
if not query.value(0):
continue
child_item = TreeItem(self.db, self.child_count, self)
self.child_items.append(child_item)
self.child_count += 1
child_item.setUpLevel1(query.value(0), query.value(1))
def setUpLevel1(self, comm_id, comm):
self.query_done = True;
self.comm_id = comm_id
self.data[0] = comm
self.child_items = []
self.child_count = 0
query = QSqlQuery(self.db)
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))
if not ret:
raise Exception("Query failed: " + query.lastError().text())
while query.next():
child_item = TreeItem(self.db, self.child_count, self)
self.child_items.append(child_item)
self.child_count += 1
child_item.setUpLevel2(comm_id, query.value(0), query.value(1), query.value(2))
def setUpLevel2(self, comm_id, thread_id, pid, tid):
self.comm_id = comm_id
self.thread_id = thread_id
self.data[0] = str(pid) + ":" + str(tid)
def getChildItem(self, row):
return self.child_items[row]
def getParentItem(self):
return self.parent_item
def getRow(self):
return self.row
def timePercent(self, b):
if not self.time:
return "0.0"
x = (b * Decimal(100)) / self.time
return str(x.quantize(Decimal('.1'), rounding=ROUND_HALF_UP))
def branchPercent(self, b):
if not self.branch_count:
return "0.0"
x = (b * Decimal(100)) / self.branch_count
return str(x.quantize(Decimal('.1'), rounding=ROUND_HALF_UP))
def addChild(self, call_path_id, name, dso, count, time, branch_count):
child_item = TreeItem(self.db, self.child_count, self)
child_item.comm_id = self.comm_id
child_item.thread_id = self.thread_id
child_item.call_path_id = call_path_id
child_item.branch_count = branch_count
child_item.time = time
child_item.data[0] = name
if dso == "[kernel.kallsyms]":
dso = "[kernel]"
child_item.data[1] = dso
child_item.data[2] = str(count)
child_item.data[3] = str(time)
child_item.data[4] = self.timePercent(time)
child_item.data[5] = str(branch_count)
child_item.data[6] = self.branchPercent(branch_count)
self.child_items.append(child_item)
self.child_count += 1
def selectCalls(self):
self.query_done = True;
query = QSqlQuery(self.db)
ret = query.exec_('SELECT id, call_path_id, branch_count, call_time, return_time, '
'( SELECT name FROM symbols WHERE id = ( SELECT symbol_id FROM call_paths WHERE id = call_path_id ) ), '
'( 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 ) ) ), '
'( SELECT ip FROM call_paths where id = call_path_id ) '
'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) +
' ORDER BY call_path_id')
if not ret:
raise Exception("Query failed: " + query.lastError().text())
last_call_path_id = 0
name = ""
dso = ""
count = 0
branch_count = 0
total_branch_count = 0
time = 0
total_time = 0
while query.next():
if query.value(1) == last_call_path_id:
count += 1
branch_count += query.value(2)
time += query.value(4) - query.value(3)
else:
if count:
self.addChild(last_call_path_id, name, dso, count, time, branch_count)
last_call_path_id = query.value(1)
name = query.value(5)
dso = query.value(6)
count = 1
total_branch_count += branch_count
total_time += time
branch_count = query.value(2)
time = query.value(4) - query.value(3)
if count:
self.addChild(last_call_path_id, name, dso, count, time, branch_count)
total_branch_count += branch_count
total_time += time
# Top level does not have time or branch count, so fix that here
if total_branch_count > self.branch_count:
self.branch_count = total_branch_count
if self.branch_count:
for child_item in self.child_items:
child_item.data[6] = self.branchPercent(child_item.branch_count)
if total_time > self.time:
self.time = total_time
if self.time:
for child_item in self.child_items:
child_item.data[4] = self.timePercent(child_item.time)
def childCount(self):
if not self.query_done:
self.selectCalls()
return self.child_count
def columnCount(self):
return 7
def columnHeader(self, column):
headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]
return headers[column]
def getData(self, column):
return self.data[column]
class TreeModel(QAbstractItemModel):
def __init__(self, db, parent=None):
super(TreeModel, self).__init__(parent)
self.db = db
self.root = TreeItem(db, 0, None)
def columnCount(self, parent):
return self.root.columnCount()
def rowCount(self, parent):
if parent.isValid():
parent_item = parent.internalPointer()
else:
parent_item = self.root
return parent_item.childCount()
def headerData(self, section, orientation, role):
if role == Qt.TextAlignmentRole:
if section > 1:
return Qt.AlignRight
if role != Qt.DisplayRole:
return None
if orientation != Qt.Horizontal:
return None
return self.root.columnHeader(section)
def parent(self, child):
child_item = child.internalPointer()
if child_item is self.root:
return QModelIndex()
parent_item = child_item.getParentItem()
return self.createIndex(parent_item.getRow(), 0, parent_item)
def index(self, row, column, parent):
if parent.isValid():
parent_item = parent.internalPointer()
else:
parent_item = self.root
child_item = parent_item.getChildItem(row)
return self.createIndex(row, column, child_item)
def data(self, index, role):
if role == Qt.TextAlignmentRole:
if index.column() > 1:
return Qt.AlignRight
if role != Qt.DisplayRole:
return None
index_item = index.internalPointer()
return index_item.getData(index.column())
class MainWindow(QMainWindow):
def __init__(self, db, dbname, parent=None):
super(MainWindow, self).__init__(parent)
self.setObjectName("MainWindow")
self.setWindowTitle("Call Graph: " + dbname)
self.move(100, 100)
self.resize(800, 600)
style = self.style()
icon = style.standardIcon(QStyle.SP_MessageBoxInformation)
self.setWindowIcon(icon);
self.model = TreeModel(db)
self.view = QTreeView()
self.view.setModel(self.model)
self.setCentralWidget(self.view)
if __name__ == '__main__':
if (len(sys.argv) < 2):
print >> sys.stderr, "Usage is: call-graph-from-sql.py <database name>"
raise Exception("Too few arguments")
dbname = sys.argv[1]
is_sqlite3 = False
try:
f = open(dbname)
if f.read(15) == "SQLite format 3":
is_sqlite3 = True
f.close()
except:
pass
if is_sqlite3:
db = QSqlDatabase.addDatabase('QSQLITE')
else:
db = QSqlDatabase.addDatabase('QPSQL')
opts = dbname.split()
for opt in opts:
if '=' in opt:
opt = opt.split('=')
if opt[0] == 'hostname':
db.setHostName(opt[1])
elif opt[0] == 'port':
db.setPort(int(opt[1]))
elif opt[0] == 'username':
db.setUserName(opt[1])
elif opt[0] == 'password':
db.setPassword(opt[1])
elif opt[0] == 'dbname':
dbname = opt[1]
else:
dbname = opt
db.setDatabaseName(dbname)
if not db.open():
raise Exception("Failed to open database " + dbname + " error: " + db.lastError().text())
app = QApplication(sys.argv)
window = MainWindow(db, dbname)
window.show()
err = app.exec_()
db.close()
sys.exit(err)

View File

@ -59,7 +59,7 @@ import datetime
# pt_example=# \q # pt_example=# \q
# #
# An example of using the database is provided by the script # An example of using the database is provided by the script
# call-graph-from-sql.py. Refer to that script for details. # exported-sql-viewer.py. Refer to that script for details.
# #
# Tables: # Tables:
# #

View File

@ -40,7 +40,7 @@ import datetime
# sqlite> .quit # sqlite> .quit
# #
# An example of using the database is provided by the script # An example of using the database is provided by the script
# call-graph-from-sql.py. Refer to that script for details. # exported-sql-viewer.py. Refer to that script for details.
# #
# The database structure is practically the same as created by the script # The database structure is practically the same as created by the script
# export-to-postgresql.py. Refer to that script for details. A notable # export-to-postgresql.py. Refer to that script for details. A notable

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@ ifeq ($(SRCARCH),$(filter $(SRCARCH),x86))
libperf-y += ioctl.o libperf-y += ioctl.o
endif endif
libperf-y += kcmp.o libperf-y += kcmp.o
libperf-y += mount_flags.o
libperf-y += pkey_alloc.o libperf-y += pkey_alloc.o
libperf-y += prctl.o libperf-y += prctl.o
libperf-y += sockaddr.o libperf-y += sockaddr.o

View File

@ -24,6 +24,7 @@ struct strarray {
} }
size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val); size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val);
size_t strarray__scnprintf_flags(struct strarray *sa, char *bf, size_t size, unsigned long flags);
struct trace; struct trace;
struct thread; struct thread;
@ -122,6 +123,12 @@ size_t syscall_arg__scnprintf_kcmp_type(char *bf, size_t size, struct syscall_ar
size_t syscall_arg__scnprintf_kcmp_idx(char *bf, size_t size, struct syscall_arg *arg); size_t syscall_arg__scnprintf_kcmp_idx(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_KCMP_IDX syscall_arg__scnprintf_kcmp_idx #define SCA_KCMP_IDX syscall_arg__scnprintf_kcmp_idx
unsigned long syscall_arg__mask_val_mount_flags(struct syscall_arg *arg, unsigned long flags);
#define SCAMV_MOUNT_FLAGS syscall_arg__mask_val_mount_flags
size_t syscall_arg__scnprintf_mount_flags(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_MOUNT_FLAGS syscall_arg__scnprintf_mount_flags
size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg); size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights #define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights

View File

@ -1,9 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1
/* /*
* trace/beauty/cone.c * trace/beauty/cone.c
* *
* Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
*
* Released under the GPL v2. (and only v2, not any later version)
*/ */
#include "trace/beauty/beauty.h" #include "trace/beauty/beauty.h"

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: LGPL-2.1
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/drm/ [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/drm/

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#ifndef EFD_SEMAPHORE #ifndef EFD_SEMAPHORE
#define EFD_SEMAPHORE 1 #define EFD_SEMAPHORE 1
#endif #endif

View File

@ -1,9 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1
/* /*
* trace/beauty/fcntl.c * trace/beauty/fcntl.c
* *
* Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
*
* Released under the GPL v2. (and only v2, not any later version)
*/ */
#include "trace/beauty/beauty.h" #include "trace/beauty/beauty.h"

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#include "trace/beauty/beauty.h" #include "trace/beauty/beauty.h"
#include <linux/kernel.h> #include <linux/kernel.h>

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#include <linux/futex.h> #include <linux/futex.h>
#ifndef FUTEX_WAIT_BITSET #ifndef FUTEX_WAIT_BITSET

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#include <linux/futex.h> #include <linux/futex.h>
#ifndef FUTEX_BITSET_MATCH_ANY #ifndef FUTEX_BITSET_MATCH_ANY

View File

@ -1,9 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1
/* /*
* trace/beauty/ioctl.c * trace/beauty/ioctl.c
* *
* Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
*
* Released under the GPL v2. (and only v2, not any later version)
*/ */
#include "trace/beauty/beauty.h" #include "trace/beauty/beauty.h"

View File

@ -1,9 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1
/* /*
* trace/beauty/kcmp.c * trace/beauty/kcmp.c
* *
* Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
*
* Released under the GPL v2. (and only v2, not any later version)
*/ */
#include "trace/beauty/beauty.h" #include "trace/beauty/beauty.h"

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: LGPL-2.1
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: LGPL-2.1
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: LGPL-2.1
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/ [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#include <uapi/linux/mman.h> #include <uapi/linux/mman.h>
#include <linux/log2.h>
static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
struct syscall_arg *arg) struct syscall_arg *arg)
@ -30,50 +31,23 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot #define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
static size_t mmap__scnprintf_flags(unsigned long flags, char *bf, size_t size)
{
#include "trace/beauty/generated/mmap_flags_array.c"
static DEFINE_STRARRAY(mmap_flags);
return strarray__scnprintf_flags(&strarray__mmap_flags, bf, size, flags);
}
static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
struct syscall_arg *arg) struct syscall_arg *arg)
{ {
int printed = 0, flags = arg->val; unsigned long flags = arg->val;
if (flags & MAP_ANONYMOUS) if (flags & MAP_ANONYMOUS)
arg->mask |= (1 << 4) | (1 << 5); /* Mask 4th ('fd') and 5th ('offset') args, ignored */ arg->mask |= (1 << 4) | (1 << 5); /* Mask 4th ('fd') and 5th ('offset') args, ignored */
#define P_MMAP_FLAG(n) \ return mmap__scnprintf_flags(flags, bf, size);
if (flags & MAP_##n) { \
printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
flags &= ~MAP_##n; \
}
P_MMAP_FLAG(SHARED);
P_MMAP_FLAG(PRIVATE);
#ifdef MAP_32BIT
P_MMAP_FLAG(32BIT);
#endif
P_MMAP_FLAG(ANONYMOUS);
P_MMAP_FLAG(DENYWRITE);
P_MMAP_FLAG(EXECUTABLE);
P_MMAP_FLAG(FILE);
P_MMAP_FLAG(FIXED);
#ifdef MAP_FIXED_NOREPLACE
P_MMAP_FLAG(FIXED_NOREPLACE);
#endif
P_MMAP_FLAG(GROWSDOWN);
P_MMAP_FLAG(HUGETLB);
P_MMAP_FLAG(LOCKED);
P_MMAP_FLAG(NONBLOCK);
P_MMAP_FLAG(NORESERVE);
P_MMAP_FLAG(POPULATE);
P_MMAP_FLAG(STACK);
P_MMAP_FLAG(UNINITIALIZED);
#ifdef MAP_SYNC
P_MMAP_FLAG(SYNC);
#endif
#undef P_MMAP_FLAG
if (flags)
printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
return printed;
} }
#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags #define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags

View File

@ -0,0 +1,32 @@
#!/bin/sh
# SPDX-License-Identifier: LGPL-2.1
if [ $# -ne 2 ] ; then
[ $# -eq 1 ] && hostarch=$1 || hostarch=`uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/`
header_dir=tools/include/uapi/asm-generic
arch_header_dir=tools/arch/${hostarch}/include/uapi/asm
else
header_dir=$1
arch_header_dir=$2
fi
arch_mman=${arch_header_dir}/mman.h
# those in egrep -vw are flags, we want just the bits
printf "static const char *mmap_flags[] = {\n"
regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MAP_([[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*.*'
egrep -q $regex ${arch_mman} && \
(egrep $regex ${arch_mman} | \
sed -r "s/$regex/\2 \1/g" | \
xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n")
egrep -q '#[[:space:]]*include[[:space:]]+<uapi/asm-generic/mman.*' ${arch_mman} &&
(egrep $regex ${header_dir}/mman-common.h | \
egrep -vw 'MAP_(UNINITIALIZED|TYPE|SHARED_VALIDATE)' | \
sed -r "s/$regex/\2 \1/g" | \
xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n")
egrep -q '#[[:space:]]*include[[:space:]]+<uapi/asm-generic/mman.h>.*' ${arch_mman} &&
(egrep $regex ${header_dir}/mman.h | \
sed -r "s/$regex/\2 \1/g" | \
xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n")
printf "};\n"

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>

View File

@ -0,0 +1,43 @@
// SPDX-License-Identifier: LGPL-2.1
/*
* trace/beauty/mount_flags.c
*
* Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
*/
#include "trace/beauty/beauty.h"
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <sys/mount.h>
static size_t mount__scnprintf_flags(unsigned long flags, char *bf, size_t size)
{
#include "trace/beauty/generated/mount_flags_array.c"
static DEFINE_STRARRAY(mount_flags);
return strarray__scnprintf_flags(&strarray__mount_flags, bf, size, flags);
}
unsigned long syscall_arg__mask_val_mount_flags(struct syscall_arg *arg __maybe_unused, unsigned long flags)
{
// do_mount in fs/namespace.c:
/*
* Pre-0.97 versions of mount() didn't have a flags word. When the
* flags word was introduced its top half was required to have the
* magic value 0xC0ED, and this remained so until 2.4.0-test9.
* Therefore, if this magic number is present, it carries no
* information and must be discarded.
*/
if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
flags &= ~MS_MGC_MSK;
return flags;
}
size_t syscall_arg__scnprintf_mount_flags(char *bf, size_t size, struct syscall_arg *arg)
{
unsigned long flags = arg->val;
return mount__scnprintf_flags(flags, bf, size);
}

View File

@ -0,0 +1,15 @@
#!/bin/sh
# SPDX-License-Identifier: LGPL-2.1
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
printf "static const char *mount_flags[] = {\n"
regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MS_([[:alnum:]_]+)[[:space:]]+([[:digit:]]+)[[:space:]]*.*'
egrep $regex ${header_dir}/fs.h | egrep -v '(MSK|VERBOSE|MGC_VAL)\>' | \
sed -r "s/$regex/\2 \2 \1/g" | sort -n | \
xargs printf "\t[%s ? (ilog2(%s) + 1) : 0] = \"%s\",\n"
regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MS_([[:alnum:]_]+)[[:space:]]+\(1<<([[:digit:]]+)\)[[:space:]]*.*'
egrep $regex ${header_dir}/fs.h | \
sed -r "s/$regex/\2 \1/g" | \
xargs printf "\t[%s + 1] = \"%s\",\n"
printf "};\n"

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#ifndef PERF_FLAG_FD_NO_GROUP #ifndef PERF_FLAG_FD_NO_GROUP
# define PERF_FLAG_FD_NO_GROUP (1UL << 0) # define PERF_FLAG_FD_NO_GROUP (1UL << 0)
#endif #endif

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: LGPL-2.1
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/

View File

@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg) size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
{ {
int pid = arg->val; int pid = arg->val;

View File

@ -1,40 +1,36 @@
// SPDX-License-Identifier: LGPL-2.1
/* /*
* trace/beauty/pkey_alloc.c * trace/beauty/pkey_alloc.c
* *
* Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
*
* Released under the GPL v2. (and only v2, not any later version)
*/ */
#include "trace/beauty/beauty.h" #include "trace/beauty/beauty.h"
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/log2.h> #include <linux/log2.h>
static size_t pkey_alloc__scnprintf_access_rights(int access_rights, char *bf, size_t size) size_t strarray__scnprintf_flags(struct strarray *sa, char *bf, size_t size, unsigned long flags)
{ {
int i, printed = 0; int i, printed = 0;
#include "trace/beauty/generated/pkey_alloc_access_rights_array.c" if (flags == 0) {
static DEFINE_STRARRAY(pkey_alloc_access_rights); const char *s = sa->entries[0];
if (access_rights == 0) {
const char *s = strarray__pkey_alloc_access_rights.entries[0];
if (s) if (s)
return scnprintf(bf, size, "%s", s); return scnprintf(bf, size, "%s", s);
return scnprintf(bf, size, "%d", 0); return scnprintf(bf, size, "%d", 0);
} }
for (i = 1; i < strarray__pkey_alloc_access_rights.nr_entries; ++i) { for (i = 1; i < sa->nr_entries; ++i) {
int bit = 1 << (i - 1); unsigned long bit = 1UL << (i - 1);
if (!(access_rights & bit)) if (!(flags & bit))
continue; continue;
if (printed != 0) if (printed != 0)
printed += scnprintf(bf + printed, size - printed, "|"); printed += scnprintf(bf + printed, size - printed, "|");
if (strarray__pkey_alloc_access_rights.entries[i] != NULL) if (sa->entries[i] != NULL)
printed += scnprintf(bf + printed, size - printed, "%s", strarray__pkey_alloc_access_rights.entries[i]); printed += scnprintf(bf + printed, size - printed, "%s", sa->entries[i]);
else else
printed += scnprintf(bf + printed, size - printed, "0x%#", bit); printed += scnprintf(bf + printed, size - printed, "0x%#", bit);
} }
@ -42,6 +38,14 @@ static size_t pkey_alloc__scnprintf_access_rights(int access_rights, char *bf, s
return printed; return printed;
} }
static size_t pkey_alloc__scnprintf_access_rights(int access_rights, char *bf, size_t size)
{
#include "trace/beauty/generated/pkey_alloc_access_rights_array.c"
static DEFINE_STRARRAY(pkey_alloc_access_rights);
return strarray__scnprintf_flags(&strarray__pkey_alloc_access_rights, bf, size, access_rights);
}
size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg) size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg)
{ {
unsigned long cmd = arg->val; unsigned long cmd = arg->val;

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: LGPL-2.1
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/ [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/

View File

@ -1,9 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1
/* /*
* trace/beauty/prctl.c * trace/beauty/prctl.c
* *
* Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
*
* Released under the GPL v2. (and only v2, not any later version)
*/ */
#include "trace/beauty/beauty.h" #include "trace/beauty/beauty.h"

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: LGPL-2.1
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#include <sched.h> #include <sched.h>
/* /*

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#ifndef SECCOMP_SET_MODE_STRICT #ifndef SECCOMP_SET_MODE_STRICT
#define SECCOMP_SET_MODE_STRICT 0 #define SECCOMP_SET_MODE_STRICT 0
#endif #endif

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#include <signal.h> #include <signal.h>
static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg) static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: LGPL-2.1
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/ [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: LGPL-2.1
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/ [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
// Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> // Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
#include "trace/beauty/beauty.h" #include "trace/beauty/beauty.h"

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
/* /*
* trace/beauty/socket.c * trace/beauty/socket.c
* *

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: LGPL-2.1
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>

View File

@ -1,9 +1,8 @@
// SPDX-License-Identifier: LGPL-2.1
/* /*
* trace/beauty/statx.c * trace/beauty/statx.c
* *
* Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
*
* Released under the GPL v2. (and only v2, not any later version)
*/ */
#include "trace/beauty/beauty.h" #include "trace/beauty/beauty.h"

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: LGPL-2.1
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: LGPL-2.1
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>

View File

@ -139,6 +139,7 @@ static int arch__associate_ins_ops(struct arch* arch, const char *name, struct i
#include "arch/x86/annotate/instructions.c" #include "arch/x86/annotate/instructions.c"
#include "arch/powerpc/annotate/instructions.c" #include "arch/powerpc/annotate/instructions.c"
#include "arch/s390/annotate/instructions.c" #include "arch/s390/annotate/instructions.c"
#include "arch/sparc/annotate/instructions.c"
static struct arch architectures[] = { static struct arch architectures[] = {
{ {
@ -170,6 +171,13 @@ static struct arch architectures[] = {
.comment_char = '#', .comment_char = '#',
}, },
}, },
{
.name = "sparc",
.init = sparc__annotate_init,
.objdump = {
.comment_char = '#',
},
},
}; };
static void ins__delete(struct ins_operands *ops) static void ins__delete(struct ins_operands *ops)

View File

@ -962,16 +962,23 @@ s64 perf_event__process_auxtrace(struct perf_session *session,
#define PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ 64 #define PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ 64
#define PERF_ITRACE_MAX_LAST_BRANCH_SZ 1024 #define PERF_ITRACE_MAX_LAST_BRANCH_SZ 1024
void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts) void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts,
bool no_sample)
{ {
synth_opts->instructions = true;
synth_opts->branches = true; synth_opts->branches = true;
synth_opts->transactions = true; synth_opts->transactions = true;
synth_opts->ptwrites = true; synth_opts->ptwrites = true;
synth_opts->pwr_events = true; synth_opts->pwr_events = true;
synth_opts->errors = true; synth_opts->errors = true;
synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE; if (no_sample) {
synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; synth_opts->period_type = PERF_ITRACE_PERIOD_INSTRUCTIONS;
synth_opts->period = 1;
synth_opts->calls = true;
} else {
synth_opts->instructions = true;
synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE;
synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
}
synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ; synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ; synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ;
synth_opts->initial_skip = 0; synth_opts->initial_skip = 0;
@ -999,7 +1006,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
} }
if (!str) { if (!str) {
itrace_synth_opts__set_default(synth_opts); itrace_synth_opts__set_default(synth_opts, false);
return 0; return 0;
} }

View File

@ -58,6 +58,7 @@ enum itrace_period_type {
/** /**
* struct itrace_synth_opts - AUX area tracing synthesis options. * struct itrace_synth_opts - AUX area tracing synthesis options.
* @set: indicates whether or not options have been set * @set: indicates whether or not options have been set
* @default_no_sample: Default to no sampling.
* @inject: indicates the event (not just the sample) must be fully synthesized * @inject: indicates the event (not just the sample) must be fully synthesized
* because 'perf inject' will write it out * because 'perf inject' will write it out
* @instructions: whether to synthesize 'instructions' events * @instructions: whether to synthesize 'instructions' events
@ -82,6 +83,7 @@ enum itrace_period_type {
*/ */
struct itrace_synth_opts { struct itrace_synth_opts {
bool set; bool set;
bool default_no_sample;
bool inject; bool inject;
bool instructions; bool instructions;
bool branches; bool branches;
@ -528,7 +530,8 @@ int perf_event__process_auxtrace_error(struct perf_session *session,
union perf_event *event); union perf_event *event);
int itrace_parse_synth_opts(const struct option *opt, const char *str, int itrace_parse_synth_opts(const struct option *opt, const char *str,
int unset); int unset);
void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts); void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts,
bool no_sample);
size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp); size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp);
void perf_session__auxtrace_error_inc(struct perf_session *session, void perf_session__auxtrace_error_inc(struct perf_session *session,

View File

@ -244,6 +244,27 @@ static void cs_etm__free(struct perf_session *session)
zfree(&aux); zfree(&aux);
} }
static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address)
{
struct machine *machine;
machine = etmq->etm->machine;
if (address >= etmq->etm->kernel_start) {
if (machine__is_host(machine))
return PERF_RECORD_MISC_KERNEL;
else
return PERF_RECORD_MISC_GUEST_KERNEL;
} else {
if (machine__is_host(machine))
return PERF_RECORD_MISC_USER;
else if (perf_guest)
return PERF_RECORD_MISC_GUEST_USER;
else
return PERF_RECORD_MISC_HYPERVISOR;
}
}
static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address, static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address,
size_t size, u8 *buffer) size_t size, u8 *buffer)
{ {
@ -258,10 +279,7 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address,
return -1; return -1;
machine = etmq->etm->machine; machine = etmq->etm->machine;
if (address >= etmq->etm->kernel_start) cpumode = cs_etm__cpu_mode(etmq, address);
cpumode = PERF_RECORD_MISC_KERNEL;
else
cpumode = PERF_RECORD_MISC_USER;
thread = etmq->thread; thread = etmq->thread;
if (!thread) { if (!thread) {
@ -653,7 +671,7 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
struct perf_sample sample = {.ip = 0,}; struct perf_sample sample = {.ip = 0,};
event->sample.header.type = PERF_RECORD_SAMPLE; event->sample.header.type = PERF_RECORD_SAMPLE;
event->sample.header.misc = PERF_RECORD_MISC_USER; event->sample.header.misc = cs_etm__cpu_mode(etmq, addr);
event->sample.header.size = sizeof(struct perf_event_header); event->sample.header.size = sizeof(struct perf_event_header);
sample.ip = addr; sample.ip = addr;
@ -665,7 +683,7 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
sample.cpu = etmq->packet->cpu; sample.cpu = etmq->packet->cpu;
sample.flags = 0; sample.flags = 0;
sample.insn_len = 1; sample.insn_len = 1;
sample.cpumode = event->header.misc; sample.cpumode = event->sample.header.misc;
if (etm->synth_opts.last_branch) { if (etm->synth_opts.last_branch) {
cs_etm__copy_last_branch_rb(etmq); cs_etm__copy_last_branch_rb(etmq);
@ -706,12 +724,15 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
u64 nr; u64 nr;
struct branch_entry entries; struct branch_entry entries;
} dummy_bs; } dummy_bs;
u64 ip;
ip = cs_etm__last_executed_instr(etmq->prev_packet);
event->sample.header.type = PERF_RECORD_SAMPLE; event->sample.header.type = PERF_RECORD_SAMPLE;
event->sample.header.misc = PERF_RECORD_MISC_USER; event->sample.header.misc = cs_etm__cpu_mode(etmq, ip);
event->sample.header.size = sizeof(struct perf_event_header); event->sample.header.size = sizeof(struct perf_event_header);
sample.ip = cs_etm__last_executed_instr(etmq->prev_packet); sample.ip = ip;
sample.pid = etmq->pid; sample.pid = etmq->pid;
sample.tid = etmq->tid; sample.tid = etmq->tid;
sample.addr = cs_etm__first_executed_instr(etmq->packet); 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)
sample.period = 1; sample.period = 1;
sample.cpu = etmq->packet->cpu; sample.cpu = etmq->packet->cpu;
sample.flags = 0; sample.flags = 0;
sample.cpumode = PERF_RECORD_MISC_USER; sample.cpumode = event->sample.header.misc;
/* /*
* perf report cannot handle events without a branch stack * perf report cannot handle events without a branch stack
@ -1432,7 +1453,8 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
if (session->itrace_synth_opts && session->itrace_synth_opts->set) { if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
etm->synth_opts = *session->itrace_synth_opts; etm->synth_opts = *session->itrace_synth_opts;
} else { } else {
itrace_synth_opts__set_default(&etm->synth_opts); itrace_synth_opts__set_default(&etm->synth_opts,
session->itrace_synth_opts->default_no_sample);
etm->synth_opts.callchain = false; etm->synth_opts.callchain = false;
} }

View File

@ -63,6 +63,7 @@ struct perf_env {
struct numa_node *numa_nodes; struct numa_node *numa_nodes;
struct memory_node *memory_nodes; struct memory_node *memory_nodes;
unsigned long long memory_bsize; unsigned long long memory_bsize;
u64 clockid_res_ns;
}; };
extern struct perf_env perf_env; extern struct perf_env perf_env;

View File

@ -308,6 +308,7 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
event->fork.pid = tgid; event->fork.pid = tgid;
event->fork.tid = pid; event->fork.tid = pid;
event->fork.header.type = PERF_RECORD_FORK; event->fork.header.type = PERF_RECORD_FORK;
event->fork.header.misc = PERF_RECORD_MISC_FORK_EXEC;
event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size); event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size);

View File

@ -358,7 +358,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)
struct perf_evsel *pos; struct perf_evsel *pos;
evlist__for_each_entry(evlist, pos) { evlist__for_each_entry(evlist, pos) {
if (!perf_evsel__is_group_leader(pos) || !pos->fd) if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->fd)
continue; continue;
perf_evsel__disable(pos); perf_evsel__disable(pos);
} }

View File

@ -232,6 +232,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
evsel->leader = evsel; evsel->leader = evsel;
evsel->unit = ""; evsel->unit = "";
evsel->scale = 1.0; evsel->scale = 1.0;
evsel->max_events = ULONG_MAX;
evsel->evlist = NULL; evsel->evlist = NULL;
evsel->bpf_fd = -1; evsel->bpf_fd = -1;
INIT_LIST_HEAD(&evsel->node); INIT_LIST_HEAD(&evsel->node);
@ -793,6 +794,9 @@ static void apply_config_terms(struct perf_evsel *evsel,
case PERF_EVSEL__CONFIG_TERM_MAX_STACK: case PERF_EVSEL__CONFIG_TERM_MAX_STACK:
max_stack = term->val.max_stack; max_stack = term->val.max_stack;
break; break;
case PERF_EVSEL__CONFIG_TERM_MAX_EVENTS:
evsel->max_events = term->val.max_events;
break;
case PERF_EVSEL__CONFIG_TERM_INHERIT: case PERF_EVSEL__CONFIG_TERM_INHERIT:
/* /*
* attr->inherit should has already been set by * 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)
int perf_evsel__enable(struct perf_evsel *evsel) int perf_evsel__enable(struct perf_evsel *evsel)
{ {
return perf_evsel__run_ioctl(evsel, int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0);
PERF_EVENT_IOC_ENABLE,
0); if (!err)
evsel->disabled = false;
return err;
} }
int perf_evsel__disable(struct perf_evsel *evsel) int perf_evsel__disable(struct perf_evsel *evsel)
{ {
return perf_evsel__run_ioctl(evsel, int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0);
PERF_EVENT_IOC_DISABLE, /*
0); * We mark it disabled here so that tools that disable a event can
* ignore events after they disable it. I.e. the ring buffer may have
* already a few more events queued up before the kernel got the stop
* request.
*/
if (!err)
evsel->disabled = true;
return err;
} }
int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)

View File

@ -46,6 +46,7 @@ enum term_type {
PERF_EVSEL__CONFIG_TERM_STACK_USER, PERF_EVSEL__CONFIG_TERM_STACK_USER,
PERF_EVSEL__CONFIG_TERM_INHERIT, PERF_EVSEL__CONFIG_TERM_INHERIT,
PERF_EVSEL__CONFIG_TERM_MAX_STACK, PERF_EVSEL__CONFIG_TERM_MAX_STACK,
PERF_EVSEL__CONFIG_TERM_MAX_EVENTS,
PERF_EVSEL__CONFIG_TERM_OVERWRITE, PERF_EVSEL__CONFIG_TERM_OVERWRITE,
PERF_EVSEL__CONFIG_TERM_DRV_CFG, PERF_EVSEL__CONFIG_TERM_DRV_CFG,
PERF_EVSEL__CONFIG_TERM_BRANCH, PERF_EVSEL__CONFIG_TERM_BRANCH,
@ -65,6 +66,7 @@ struct perf_evsel_config_term {
bool inherit; bool inherit;
bool overwrite; bool overwrite;
char *branch; char *branch;
unsigned long max_events;
} val; } val;
bool weak; bool weak;
}; };
@ -99,6 +101,8 @@ struct perf_evsel {
struct perf_counts *prev_raw_counts; struct perf_counts *prev_raw_counts;
int idx; int idx;
u32 ids; u32 ids;
unsigned long max_events;
unsigned long nr_events_printed;
char *name; char *name;
double scale; double scale;
const char *unit; const char *unit;
@ -119,6 +123,7 @@ struct perf_evsel {
bool snapshot; bool snapshot;
bool supported; bool supported;
bool needs_swap; bool needs_swap;
bool disabled;
bool no_aux_samples; bool no_aux_samples;
bool immediate; bool immediate;
bool system_wide; bool system_wide;

View File

@ -29,6 +29,12 @@ int jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_ent
#elif defined(__powerpc__) #elif defined(__powerpc__)
#define GEN_ELF_ARCH EM_PPC #define GEN_ELF_ARCH EM_PPC
#define GEN_ELF_CLASS ELFCLASS32 #define GEN_ELF_CLASS ELFCLASS32
#elif defined(__sparc__) && defined(__arch64__)
#define GEN_ELF_ARCH EM_SPARCV9
#define GEN_ELF_CLASS ELFCLASS64
#elif defined(__sparc__)
#define GEN_ELF_ARCH EM_SPARC
#define GEN_ELF_CLASS ELFCLASS32
#else #else
#error "unsupported architecture" #error "unsupported architecture"
#endif #endif

View File

@ -1034,6 +1034,13 @@ static int write_auxtrace(struct feat_fd *ff,
return err; return err;
} }
static int write_clockid(struct feat_fd *ff,
struct perf_evlist *evlist __maybe_unused)
{
return do_write(ff, &ff->ph->env.clockid_res_ns,
sizeof(ff->ph->env.clockid_res_ns));
}
static int cpu_cache_level__sort(const void *a, const void *b) static int cpu_cache_level__sort(const void *a, const void *b)
{ {
struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a; 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)
fprintf(fp, "# Core ID and Socket ID information is not available\n"); fprintf(fp, "# Core ID and Socket ID information is not available\n");
} }
static void print_clockid(struct feat_fd *ff, FILE *fp)
{
fprintf(fp, "# clockid frequency: %"PRIu64" MHz\n",
ff->ph->env.clockid_res_ns * 1000);
}
static void free_event_desc(struct perf_evsel *events) static void free_event_desc(struct perf_evsel *events)
{ {
struct perf_evsel *evsel; struct perf_evsel *evsel;
@ -2531,6 +2544,15 @@ out:
return ret; return ret;
} }
static int process_clockid(struct feat_fd *ff,
void *data __maybe_unused)
{
if (do_read_u64(ff, &ff->ph->env.clockid_res_ns))
return -1;
return 0;
}
struct feature_ops { struct feature_ops {
int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
void (*print)(struct feat_fd *ff, FILE *fp); void (*print)(struct feat_fd *ff, FILE *fp);
@ -2590,6 +2612,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
FEAT_OPN(CACHE, cache, true), FEAT_OPN(CACHE, cache, true),
FEAT_OPR(SAMPLE_TIME, sample_time, false), FEAT_OPR(SAMPLE_TIME, sample_time, false),
FEAT_OPR(MEM_TOPOLOGY, mem_topology, true), FEAT_OPR(MEM_TOPOLOGY, mem_topology, true),
FEAT_OPR(CLOCKID, clockid, false)
}; };
struct header_print_data { struct header_print_data {

View File

@ -38,6 +38,7 @@ enum {
HEADER_CACHE, HEADER_CACHE,
HEADER_SAMPLE_TIME, HEADER_SAMPLE_TIME,
HEADER_MEM_TOPOLOGY, HEADER_MEM_TOPOLOGY,
HEADER_CLOCKID,
HEADER_LAST_FEATURE, HEADER_LAST_FEATURE,
HEADER_FEAT_BITS = 256, HEADER_FEAT_BITS = 256,
}; };

View File

@ -269,6 +269,13 @@ static int intel_bts_do_fix_overlap(struct auxtrace_queue *queue,
return 0; return 0;
} }
static inline u8 intel_bts_cpumode(struct intel_bts *bts, uint64_t ip)
{
return machine__kernel_ip(bts->machine, ip) ?
PERF_RECORD_MISC_KERNEL :
PERF_RECORD_MISC_USER;
}
static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq, static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
struct branch *branch) struct branch *branch)
{ {
@ -281,12 +288,8 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
bts->num_events++ <= bts->synth_opts.initial_skip) bts->num_events++ <= bts->synth_opts.initial_skip)
return 0; return 0;
event.sample.header.type = PERF_RECORD_SAMPLE;
event.sample.header.misc = PERF_RECORD_MISC_USER;
event.sample.header.size = sizeof(struct perf_event_header);
sample.cpumode = PERF_RECORD_MISC_USER;
sample.ip = le64_to_cpu(branch->from); sample.ip = le64_to_cpu(branch->from);
sample.cpumode = intel_bts_cpumode(bts, sample.ip);
sample.pid = btsq->pid; sample.pid = btsq->pid;
sample.tid = btsq->tid; sample.tid = btsq->tid;
sample.addr = le64_to_cpu(branch->to); sample.addr = le64_to_cpu(branch->to);
@ -298,6 +301,10 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
sample.insn_len = btsq->intel_pt_insn.length; sample.insn_len = btsq->intel_pt_insn.length;
memcpy(sample.insn, btsq->intel_pt_insn.buf, INTEL_PT_INSN_BUF_SZ); memcpy(sample.insn, btsq->intel_pt_insn.buf, INTEL_PT_INSN_BUF_SZ);
event.sample.header.type = PERF_RECORD_SAMPLE;
event.sample.header.misc = sample.cpumode;
event.sample.header.size = sizeof(struct perf_event_header);
if (bts->synth_opts.inject) { if (bts->synth_opts.inject) {
event.sample.header.size = bts->branches_event_size; event.sample.header.size = bts->branches_event_size;
ret = perf_event__synthesize_sample(&event, ret = perf_event__synthesize_sample(&event,
@ -910,7 +917,8 @@ int intel_bts_process_auxtrace_info(union perf_event *event,
if (session->itrace_synth_opts && session->itrace_synth_opts->set) { if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
bts->synth_opts = *session->itrace_synth_opts; bts->synth_opts = *session->itrace_synth_opts;
} else { } else {
itrace_synth_opts__set_default(&bts->synth_opts); itrace_synth_opts__set_default(&bts->synth_opts,
session->itrace_synth_opts->default_no_sample);
if (session->itrace_synth_opts) if (session->itrace_synth_opts)
bts->synth_opts.thread_stack = bts->synth_opts.thread_stack =
session->itrace_synth_opts->thread_stack; session->itrace_synth_opts->thread_stack;

View File

@ -407,6 +407,13 @@ intel_pt_cache_lookup(struct dso *dso, struct machine *machine, u64 offset)
return auxtrace_cache__lookup(dso->auxtrace_cache, offset); return auxtrace_cache__lookup(dso->auxtrace_cache, offset);
} }
static inline u8 intel_pt_cpumode(struct intel_pt *pt, uint64_t ip)
{
return ip >= pt->kernel_start ?
PERF_RECORD_MISC_KERNEL :
PERF_RECORD_MISC_USER;
}
static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn, static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t *insn_cnt_ptr, uint64_t *ip,
uint64_t to_ip, uint64_t max_insn_cnt, 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,
if (to_ip && *ip == to_ip) if (to_ip && *ip == to_ip)
goto out_no_cache; goto out_no_cache;
if (*ip >= ptq->pt->kernel_start) cpumode = intel_pt_cpumode(ptq->pt, *ip);
cpumode = PERF_RECORD_MISC_KERNEL;
else
cpumode = PERF_RECORD_MISC_USER;
thread = ptq->thread; thread = ptq->thread;
if (!thread) { if (!thread) {
@ -759,7 +763,8 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
if (pt->synth_opts.callchain) { if (pt->synth_opts.callchain) {
size_t sz = sizeof(struct ip_callchain); size_t sz = sizeof(struct ip_callchain);
sz += pt->synth_opts.callchain_sz * sizeof(u64); /* Add 1 to callchain_sz for callchain context */
sz += (pt->synth_opts.callchain_sz + 1) * sizeof(u64);
ptq->chain = zalloc(sz); ptq->chain = zalloc(sz);
if (!ptq->chain) if (!ptq->chain)
goto out_free; goto out_free;
@ -1058,15 +1063,11 @@ static void intel_pt_prep_b_sample(struct intel_pt *pt,
union perf_event *event, union perf_event *event,
struct perf_sample *sample) struct perf_sample *sample)
{ {
event->sample.header.type = PERF_RECORD_SAMPLE;
event->sample.header.misc = PERF_RECORD_MISC_USER;
event->sample.header.size = sizeof(struct perf_event_header);
if (!pt->timeless_decoding) if (!pt->timeless_decoding)
sample->time = tsc_to_perf_time(ptq->timestamp, &pt->tc); sample->time = tsc_to_perf_time(ptq->timestamp, &pt->tc);
sample->cpumode = PERF_RECORD_MISC_USER;
sample->ip = ptq->state->from_ip; sample->ip = ptq->state->from_ip;
sample->cpumode = intel_pt_cpumode(pt, sample->ip);
sample->pid = ptq->pid; sample->pid = ptq->pid;
sample->tid = ptq->tid; sample->tid = ptq->tid;
sample->addr = ptq->state->to_ip; sample->addr = ptq->state->to_ip;
@ -1075,6 +1076,10 @@ static void intel_pt_prep_b_sample(struct intel_pt *pt,
sample->flags = ptq->flags; sample->flags = ptq->flags;
sample->insn_len = ptq->insn_len; sample->insn_len = ptq->insn_len;
memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ); memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
event->sample.header.type = PERF_RECORD_SAMPLE;
event->sample.header.misc = sample->cpumode;
event->sample.header.size = sizeof(struct perf_event_header);
} }
static int intel_pt_inject_event(union perf_event *event, static int intel_pt_inject_event(union perf_event *event,
@ -1160,7 +1165,8 @@ static void intel_pt_prep_sample(struct intel_pt *pt,
if (pt->synth_opts.callchain) { if (pt->synth_opts.callchain) {
thread_stack__sample(ptq->thread, ptq->chain, thread_stack__sample(ptq->thread, ptq->chain,
pt->synth_opts.callchain_sz, sample->ip); pt->synth_opts.callchain_sz + 1,
sample->ip, pt->kernel_start);
sample->callchain = ptq->chain; sample->callchain = ptq->chain;
} }
@ -2559,7 +2565,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
if (session->itrace_synth_opts && session->itrace_synth_opts->set) { if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
pt->synth_opts = *session->itrace_synth_opts; pt->synth_opts = *session->itrace_synth_opts;
} else { } else {
itrace_synth_opts__set_default(&pt->synth_opts); itrace_synth_opts__set_default(&pt->synth_opts,
session->itrace_synth_opts->default_no_sample);
if (use_browser != -1) { if (use_browser != -1) {
pt->synth_opts.branches = false; pt->synth_opts.branches = false;
pt->synth_opts.callchain = true; pt->synth_opts.callchain = true;

View File

@ -1708,6 +1708,7 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
struct thread *parent = machine__findnew_thread(machine, struct thread *parent = machine__findnew_thread(machine,
event->fork.ppid, event->fork.ppid,
event->fork.ptid); event->fork.ptid);
bool do_maps_clone = true;
int err = 0; int err = 0;
if (dump_trace) if (dump_trace)
@ -1736,9 +1737,25 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
thread = machine__findnew_thread(machine, event->fork.pid, thread = machine__findnew_thread(machine, event->fork.pid,
event->fork.tid); event->fork.tid);
/*
* When synthesizing FORK events, we are trying to create thread
* objects for the already running tasks on the machine.
*
* Normally, for a kernel FORK event, we want to clone the parent's
* maps because that is what the kernel just did.
*
* But when synthesizing, this should not be done. If we do, we end up
* with overlapping maps as we process the sythesized MMAP2 events that
* get delivered shortly thereafter.
*
* Use the FORK event misc flags in an internal way to signal this
* situation, so we can elide the map clone when appropriate.
*/
if (event->fork.header.misc & PERF_RECORD_MISC_FORK_EXEC)
do_maps_clone = false;
if (thread == NULL || parent == NULL || if (thread == NULL || parent == NULL ||
thread__fork(thread, parent, sample->time) < 0) { thread__fork(thread, parent, sample->time, do_maps_clone) < 0) {
dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
err = -1; err = -1;
} }
@ -2140,6 +2157,27 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
return 0; return 0;
} }
static int find_prev_cpumode(struct ip_callchain *chain, struct thread *thread,
struct callchain_cursor *cursor,
struct symbol **parent,
struct addr_location *root_al,
u8 *cpumode, int ent)
{
int err = 0;
while (--ent >= 0) {
u64 ip = chain->ips[ent];
if (ip >= PERF_CONTEXT_MAX) {
err = add_callchain_ip(thread, cursor, parent,
root_al, cpumode, ip,
false, NULL, NULL, 0);
break;
}
}
return err;
}
static int thread__resolve_callchain_sample(struct thread *thread, static int thread__resolve_callchain_sample(struct thread *thread,
struct callchain_cursor *cursor, struct callchain_cursor *cursor,
struct perf_evsel *evsel, struct perf_evsel *evsel,
@ -2246,6 +2284,12 @@ static int thread__resolve_callchain_sample(struct thread *thread,
} }
check_calls: check_calls:
if (callchain_param.order != ORDER_CALLEE) {
err = find_prev_cpumode(chain, thread, cursor, parent, root_al,
&cpumode, chain->nr - first_call);
if (err)
return (err < 0) ? err : 0;
}
for (i = first_call, nr_entries = 0; for (i = first_call, nr_entries = 0;
i < chain_nr && nr_entries < max_stack; i++) { i < chain_nr && nr_entries < max_stack; i++) {
u64 ip; u64 ip;
@ -2260,9 +2304,15 @@ check_calls:
continue; continue;
#endif #endif
ip = chain->ips[j]; ip = chain->ips[j];
if (ip < PERF_CONTEXT_MAX) if (ip < PERF_CONTEXT_MAX)
++nr_entries; ++nr_entries;
else if (callchain_param.order != ORDER_CALLEE) {
err = find_prev_cpumode(chain, thread, cursor, parent,
root_al, &cpumode, j);
if (err)
return (err < 0) ? err : 0;
continue;
}
err = add_callchain_ip(thread, cursor, parent, err = add_callchain_ip(thread, cursor, parent,
root_al, &cpumode, ip, root_al, &cpumode, ip,

View File

@ -926,6 +926,7 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
[PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit", [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit",
[PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit", [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit",
[PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack", [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack",
[PARSE_EVENTS__TERM_TYPE_MAX_EVENTS] = "nr",
[PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite",
[PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite",
[PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config", [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config",
@ -1037,6 +1038,9 @@ do { \
case PARSE_EVENTS__TERM_TYPE_MAX_STACK: case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
CHECK_TYPE_VAL(NUM); CHECK_TYPE_VAL(NUM);
break; break;
case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
CHECK_TYPE_VAL(NUM);
break;
default: default:
err->str = strdup("unknown term"); err->str = strdup("unknown term");
err->idx = term->err_term; err->idx = term->err_term;
@ -1084,6 +1088,7 @@ static int config_term_tracepoint(struct perf_event_attr *attr,
case PARSE_EVENTS__TERM_TYPE_INHERIT: case PARSE_EVENTS__TERM_TYPE_INHERIT:
case PARSE_EVENTS__TERM_TYPE_NOINHERIT: case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
case PARSE_EVENTS__TERM_TYPE_MAX_STACK: case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
case PARSE_EVENTS__TERM_TYPE_OVERWRITE: case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
return config_term_common(attr, term, err); return config_term_common(attr, term, err);
@ -1162,6 +1167,9 @@ do { \
case PARSE_EVENTS__TERM_TYPE_MAX_STACK: case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num); ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num);
break; break;
case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
ADD_CONFIG_TERM(MAX_EVENTS, max_events, term->val.num);
break;
case PARSE_EVENTS__TERM_TYPE_OVERWRITE: case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0); ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0);
break; break;

View File

@ -71,6 +71,7 @@ enum {
PARSE_EVENTS__TERM_TYPE_NOINHERIT, PARSE_EVENTS__TERM_TYPE_NOINHERIT,
PARSE_EVENTS__TERM_TYPE_INHERIT, PARSE_EVENTS__TERM_TYPE_INHERIT,
PARSE_EVENTS__TERM_TYPE_MAX_STACK, PARSE_EVENTS__TERM_TYPE_MAX_STACK,
PARSE_EVENTS__TERM_TYPE_MAX_EVENTS,
PARSE_EVENTS__TERM_TYPE_NOOVERWRITE, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE,
PARSE_EVENTS__TERM_TYPE_OVERWRITE, PARSE_EVENTS__TERM_TYPE_OVERWRITE,
PARSE_EVENTS__TERM_TYPE_DRV_CFG, PARSE_EVENTS__TERM_TYPE_DRV_CFG,

View File

@ -269,6 +269,7 @@ time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); } max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); }
nr { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_EVENTS); }
inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); }
no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); } overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); }

View File

@ -324,7 +324,17 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
plt_entry_size = 16; plt_entry_size = 16;
break; break;
default: /* FIXME: s390/alpha/mips/parisc/poperpc/sh/sparc/xtensa need to be checked */ case EM_SPARC:
plt_header_size = 48;
plt_entry_size = 12;
break;
case EM_SPARCV9:
plt_header_size = 128;
plt_entry_size = 32;
break;
default: /* FIXME: s390/alpha/mips/parisc/poperpc/sh/xtensa need to be checked */
plt_header_size = shdr_plt.sh_entsize; plt_header_size = shdr_plt.sh_entsize;
plt_entry_size = shdr_plt.sh_entsize; plt_entry_size = shdr_plt.sh_entsize;
break; break;

View File

@ -123,7 +123,8 @@ struct symbol_conf {
const char *vmlinux_name, const char *vmlinux_name,
*kallsyms_name, *kallsyms_name,
*source_prefix, *source_prefix,
*field_sep; *field_sep,
*graph_function;
const char *default_guest_vmlinux_name, const char *default_guest_vmlinux_name,
*default_guest_kallsyms, *default_guest_kallsyms,
*default_guest_modules; *default_guest_modules;

View File

@ -310,20 +310,46 @@ void thread_stack__free(struct thread *thread)
} }
} }
void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, static inline u64 callchain_context(u64 ip, u64 kernel_start)
size_t sz, u64 ip)
{ {
size_t i; return ip < kernel_start ? PERF_CONTEXT_USER : PERF_CONTEXT_KERNEL;
}
if (!thread || !thread->ts) void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
chain->nr = 1; size_t sz, u64 ip, u64 kernel_start)
else {
chain->nr = min(sz, thread->ts->cnt + 1); u64 context = callchain_context(ip, kernel_start);
u64 last_context;
size_t i, j;
chain->ips[0] = ip; if (sz < 2) {
chain->nr = 0;
return;
}
for (i = 1; i < chain->nr; i++) chain->ips[0] = context;
chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr; chain->ips[1] = ip;
if (!thread || !thread->ts) {
chain->nr = 2;
return;
}
last_context = context;
for (i = 2, j = 1; i < sz && j <= thread->ts->cnt; i++, j++) {
ip = thread->ts->stack[thread->ts->cnt - j].ret_addr;
context = callchain_context(ip, kernel_start);
if (context != last_context) {
if (i >= sz - 1)
break;
chain->ips[i++] = context;
last_context = context;
}
chain->ips[i] = ip;
}
chain->nr = i;
} }
struct call_return_processor * struct call_return_processor *

View File

@ -84,7 +84,7 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
u64 to_ip, u16 insn_len, u64 trace_nr); u64 to_ip, u16 insn_len, u64 trace_nr);
void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr); void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr);
void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
size_t sz, u64 ip); size_t sz, u64 ip, u64 kernel_start);
int thread_stack__flush(struct thread *thread); int thread_stack__flush(struct thread *thread);
void thread_stack__free(struct thread *thread); void thread_stack__free(struct thread *thread);
size_t thread_stack__depth(struct thread *thread); size_t thread_stack__depth(struct thread *thread);

View File

@ -330,7 +330,8 @@ static int thread__prepare_access(struct thread *thread)
} }
static int thread__clone_map_groups(struct thread *thread, static int thread__clone_map_groups(struct thread *thread,
struct thread *parent) struct thread *parent,
bool do_maps_clone)
{ {
/* This is new thread, we share map groups for process. */ /* This is new thread, we share map groups for process. */
if (thread->pid_ == parent->pid_) if (thread->pid_ == parent->pid_)
@ -341,15 +342,11 @@ static int thread__clone_map_groups(struct thread *thread,
thread->pid_, thread->tid, parent->pid_, parent->tid); thread->pid_, thread->tid, parent->pid_, parent->tid);
return 0; return 0;
} }
/* But this one is new process, copy maps. */ /* But this one is new process, copy maps. */
if (map_groups__clone(thread, parent->mg) < 0) return do_maps_clone ? map_groups__clone(thread, parent->mg) : 0;
return -ENOMEM;
return 0;
} }
int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone)
{ {
if (parent->comm_set) { if (parent->comm_set) {
const char *comm = thread__comm_str(parent); const char *comm = thread__comm_str(parent);
@ -362,7 +359,7 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
} }
thread->ppid = parent->tid; thread->ppid = parent->tid;
return thread__clone_map_groups(thread, parent); return thread__clone_map_groups(thread, parent, do_maps_clone);
} }
void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, void thread__find_cpumode_addr_location(struct thread *thread, u64 addr,

Some files were not shown because too many files have changed in this diff Show More