提交 48342fc0 编写于 作者: L Linus Torvalds

Merge tag 'perf-tools-2020-12-19' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tools updates from Arnaldo Carvalho de Melo:
 "perf record:
   - Fix memory leak when using '--user-regs=?' to list registers

  aarch64 support:
   - Add aarch64 registers to 'perf record's' --user-regs command line
     option

  aarch64 hw tracing support:
   - Decode memory tagging properties
   - Improve ARM's auxtrace support
   - Add support for ARMv8.3-SPE

  perf kvm:
   - Add kvm-stat for arm64

  perf stat:
   - Add --quiet option

  Cleanups:
   - Fixup function names wrt what is in libperf and what is in
     tools/perf

  Build:
   - Allow building without libbpf in older systems

  New kernel features:
   - Initial support for data/code page size sample type, more to come

  perf annotate:
   - Support MIPS instruction extended support

  perf stack unwinding:
   - Fix separate debug info files when using elfutils' libdw's unwinder

  perf vendor events:
   - Update Intel's Skylake client events to v50
   - Add JSON metrics for ARM's imx8mm DDR Perf
   - Support printing metric groups for system PMUs

  perf build id:
   - Prep work for supporting having the build id provided by the kernel
     in PERF_RECORD_MMAP2 metadata events

  perf stat:
   - Support regex pattern in --for-each-cgroup

  pipe mode:
   - Allow to use stdio functions for pipe mode
   - Support 'perf report's' --header-only for pipe mode
   - Support pipe mode display in 'perf evlist'

  Documentation:
   - Update information about CAP_PERFMON"

* tag 'perf-tools-2020-12-19' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux: (134 commits)
  perf mem: Factor out a function to generate sort order
  perf sort: Add sort option for data page size
  perf script: Support data page size
  tools headers UAPI: Update asm-generic/unistd.h
  tools headers cpufeatures: Sync with the kernel sources
  tools headers UAPI: Sync linux/prctl.h with the kernel sources
  tools headers UAPI: Sync linux/fscrypt.h with the kernel sources
  tools headers UAPI: Sync linux/const.h with the kernel headers
  tools arch x86: Sync the msr-index.h copy with the kernel sources
  perf trace beauty: Update copy of linux/socket.h with the kernel sources
  tools headers: Update linux/ctype.h with the kernel sources
  tools headers: Add conditional __has_builtin()
  tools headers: Get tools's linux/compiler.h closer to the kernel's
  tools headers UAPI: Sync linux/stat.h with the kernel sources
  tools headers: Syncronize linux/build_bug.h with the kernel sources
  perf tools: Reformat record's control fd man text
  perf config: Fix example command in manpage to conform to syntax specified in the SYNOPSIS section.
  perf test: Make sample-parsing test aware of PERF_SAMPLE_{CODE,DATA}_PAGE_SIZE
  perf tools: Add support to read build id from compressed elf
  perf debug: Add debug_set_file function
  ...
......@@ -84,11 +84,14 @@ capabilities then providing the process with CAP_PERFMON capability singly
is recommended as the preferred secure approach to resolve double access
denial logging related to usage of performance monitoring and observability.
Unprivileged processes using perf_events system call are also subject
for PTRACE_MODE_READ_REALCREDS ptrace access mode check [7]_ , whose
outcome determines whether monitoring is permitted. So unprivileged
processes provided with CAP_SYS_PTRACE capability are effectively
permitted to pass the check.
Prior Linux v5.9 unprivileged processes using perf_events system call
are also subject for PTRACE_MODE_READ_REALCREDS ptrace access mode check
[7]_ , whose outcome determines whether monitoring is permitted.
So unprivileged processes provided with CAP_SYS_PTRACE capability are
effectively permitted to pass the check. Starting from Linux v5.9
CAP_SYS_PTRACE capability is not required and CAP_PERFMON is enough to
be provided for processes to make performance monitoring and observability
operations.
Other capabilities being granted to unprivileged processes can
effectively enable capturing of additional data required for later
......@@ -99,11 +102,11 @@ CAP_SYSLOG capability permits reading kernel space memory addresses from
Privileged Perf users groups
---------------------------------
Mechanisms of capabilities, privileged capability-dumb files [6]_ and
file system ACLs [10]_ can be used to create dedicated groups of
privileged Perf users who are permitted to execute performance monitoring
and observability without scope limits. The following steps can be
taken to create such groups of privileged Perf users.
Mechanisms of capabilities, privileged capability-dumb files [6]_,
file system ACLs [10]_ and sudo [15]_ utility can be used to create
dedicated groups of privileged Perf users who are permitted to execute
performance monitoring and observability without limits. The following
steps can be taken to create such groups of privileged Perf users.
1. Create perf_users group of privileged Perf users, assign perf_users
group to Perf tool executable and limit access to the executable for
......@@ -133,7 +136,7 @@ taken to create such groups of privileged Perf users.
# getcap perf
perf = cap_sys_ptrace,cap_syslog,cap_perfmon+ep
If the libcap installed doesn't yet support "cap_perfmon", use "38" instead,
If the libcap [16]_ installed doesn't yet support "cap_perfmon", use "38" instead,
i.e.:
::
......@@ -159,6 +162,60 @@ performance monitoring and observability by using functionality of the
configured Perf tool executable that, when executes, passes perf_events
subsystem scope checks.
In case Perf tool executable can't be assigned required capabilities (e.g.
file system is mounted with nosuid option or extended attributes are
not supported by the file system) then creation of the capabilities
privileged environment, naturally shell, is possible. The shell provides
inherent processes with CAP_PERFMON and other required capabilities so that
performance monitoring and observability operations are available in the
environment without limits. Access to the environment can be open via sudo
utility for members of perf_users group only. In order to create such
environment:
1. Create shell script that uses capsh utility [16]_ to assign CAP_PERFMON
and other required capabilities into ambient capability set of the shell
process, lock the process security bits after enabling SECBIT_NO_SETUID_FIXUP,
SECBIT_NOROOT and SECBIT_NO_CAP_AMBIENT_RAISE bits and then change
the process identity to sudo caller of the script who should essentially
be a member of perf_users group:
::
# ls -alh /usr/local/bin/perf.shell
-rwxr-xr-x. 1 root root 83 Oct 13 23:57 /usr/local/bin/perf.shell
# cat /usr/local/bin/perf.shell
exec /usr/sbin/capsh --iab=^cap_perfmon --secbits=239 --user=$SUDO_USER -- -l
2. Extend sudo policy at /etc/sudoers file with a rule for perf_users group:
::
# grep perf_users /etc/sudoers
%perf_users ALL=/usr/local/bin/perf.shell
3. Check that members of perf_users group have access to the privileged
shell and have CAP_PERFMON and other required capabilities enabled
in permitted, effective and ambient capability sets of an inherent process:
::
$ id
uid=1003(capsh_test) gid=1004(capsh_test) groups=1004(capsh_test),1000(perf_users) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
$ sudo perf.shell
[sudo] password for capsh_test:
$ grep Cap /proc/self/status
CapInh: 0000004000000000
CapPrm: 0000004000000000
CapEff: 0000004000000000
CapBnd: 000000ffffffffff
CapAmb: 0000004000000000
$ capsh --decode=0000004000000000
0x0000004000000000=cap_perfmon
As a result, members of perf_users group have access to the privileged
environment where they can use tools employing performance monitoring APIs
governed by CAP_PERFMON Linux capability.
This specific access control management is only available to superuser
or root running processes with CAP_SETPCAP, CAP_SETFCAP [6]_
capabilities.
......@@ -264,3 +321,5 @@ Bibliography
.. [12] `<http://man7.org/linux/man-pages/man5/limits.conf.5.html>`_
.. [13] `<https://sites.google.com/site/fullycapable>`_
.. [14] `<http://man7.org/linux/man-pages/man8/auditd.8.html>`_
.. [15] `<https://man7.org/linux/man-pages/man8/sudo.8.html>`_
.. [16] `<https://git.kernel.org/pub/scm/libs/libcap/libcap.git/>`_
......@@ -241,6 +241,7 @@
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */
#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/
#define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* TSC adjustment MSR 0x3B */
#define X86_FEATURE_SGX ( 9*32+ 2) /* Software Guard Extensions */
#define X86_FEATURE_BMI1 ( 9*32+ 3) /* 1st group bit manipulation extensions */
#define X86_FEATURE_HLE ( 9*32+ 4) /* Hardware Lock Elision */
#define X86_FEATURE_AVX2 ( 9*32+ 5) /* AVX2 instructions */
......@@ -356,6 +357,7 @@
#define X86_FEATURE_MOVDIRI (16*32+27) /* MOVDIRI instruction */
#define X86_FEATURE_MOVDIR64B (16*32+28) /* MOVDIR64B instruction */
#define X86_FEATURE_ENQCMD (16*32+29) /* ENQCMD and ENQCMDS instructions */
#define X86_FEATURE_SGX_LC (16*32+30) /* Software Guard Extensions Launch Control */
/* AMD-defined CPU features, CPUID level 0x80000007 (EBX), word 17 */
#define X86_FEATURE_OVERFLOW_RECOV (17*32+ 0) /* MCA overflow recovery support */
......
......@@ -62,6 +62,12 @@
# define DISABLE_ENQCMD (1 << (X86_FEATURE_ENQCMD & 31))
#endif
#ifdef CONFIG_X86_SGX
# define DISABLE_SGX 0
#else
# define DISABLE_SGX (1 << (X86_FEATURE_SGX & 31))
#endif
/*
* Make sure to add features to the correct mask
*/
......@@ -74,7 +80,7 @@
#define DISABLED_MASK6 0
#define DISABLED_MASK7 (DISABLE_PTI)
#define DISABLED_MASK8 0
#define DISABLED_MASK9 (DISABLE_SMAP)
#define DISABLED_MASK9 (DISABLE_SMAP|DISABLE_SGX)
#define DISABLED_MASK10 0
#define DISABLED_MASK11 0
#define DISABLED_MASK12 0
......
......@@ -139,6 +139,7 @@
#define MSR_IA32_MCG_CAP 0x00000179
#define MSR_IA32_MCG_STATUS 0x0000017a
#define MSR_IA32_MCG_CTL 0x0000017b
#define MSR_ERROR_CONTROL 0x0000017f
#define MSR_IA32_MCG_EXT_CTL 0x000004d0
#define MSR_OFFCORE_RSP_0 0x000001a6
......@@ -326,8 +327,9 @@
#define MSR_PP1_ENERGY_STATUS 0x00000641
#define MSR_PP1_POLICY 0x00000642
#define MSR_AMD_PKG_ENERGY_STATUS 0xc001029b
#define MSR_AMD_RAPL_POWER_UNIT 0xc0010299
#define MSR_AMD_CORE_ENERGY_STATUS 0xc001029a
#define MSR_AMD_PKG_ENERGY_STATUS 0xc001029b
/* Config TDP MSRs */
#define MSR_CONFIG_TDP_NOMINAL 0x00000648
......@@ -609,6 +611,8 @@
#define FEAT_CTL_LOCKED BIT(0)
#define FEAT_CTL_VMX_ENABLED_INSIDE_SMX BIT(1)
#define FEAT_CTL_VMX_ENABLED_OUTSIDE_SMX BIT(2)
#define FEAT_CTL_SGX_LC_ENABLED BIT(17)
#define FEAT_CTL_SGX_ENABLED BIT(18)
#define FEAT_CTL_LMCE_ENABLED BIT(20)
#define MSR_IA32_TSC_ADJUST 0x0000003b
......@@ -628,6 +632,12 @@
#define MSR_IA32_UCODE_WRITE 0x00000079
#define MSR_IA32_UCODE_REV 0x0000008b
/* Intel SGX Launch Enclave Public Key Hash MSRs */
#define MSR_IA32_SGXLEPUBKEYHASH0 0x0000008C
#define MSR_IA32_SGXLEPUBKEYHASH1 0x0000008D
#define MSR_IA32_SGXLEPUBKEYHASH2 0x0000008E
#define MSR_IA32_SGXLEPUBKEYHASH3 0x0000008F
#define MSR_IA32_SMM_MONITOR_CTL 0x0000009b
#define MSR_IA32_SMBASE 0x0000009e
......
......@@ -90,7 +90,7 @@ __BUILDXX = $(CXX) $(CXXFLAGS) -MD -Wall -Werror -o $@ $(patsubst %.bin,%.cpp,$(
###############################
$(OUTPUT)test-all.bin:
$(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -I/usr/include/slang -lslang $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz -llzma -lzstd
$(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -I/usr/include/slang -lslang $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz -llzma -lzstd -lcap
$(OUTPUT)test-hello.bin:
$(BUILD)
......
......@@ -79,4 +79,9 @@
#define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
#endif // static_assert
#ifdef __GENKSYMS__
/* genksyms gets confused by _Static_assert */
#define _Static_assert(expr, ...)
#endif
#endif /* _LINUX_BUILD_BUG_H */
......@@ -2,9 +2,7 @@
#ifndef _TOOLS_LINUX_COMPILER_H_
#define _TOOLS_LINUX_COMPILER_H_
#ifdef __GNUC__
#include <linux/compiler-gcc.h>
#endif
#include <linux/compiler_types.h>
#ifndef __compiletime_error
# define __compiletime_error(message)
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LINUX_COMPILER_TYPES_H
#define __LINUX_COMPILER_TYPES_H
/* Builtins */
/*
* __has_builtin is supported on gcc >= 10, clang >= 3 and icc >= 21.
* In the meantime, to support gcc < 10, we implement __has_builtin
* by hand.
*/
#ifndef __has_builtin
#define __has_builtin(x) (0)
#endif
/* Compiler specific macros. */
#ifdef __GNUC__
#include <linux/compiler-gcc.h>
#endif
#endif /* __LINUX_COMPILER_TYPES_H */
......@@ -2,6 +2,8 @@
#ifndef _LINUX_CTYPE_H
#define _LINUX_CTYPE_H
#include <linux/compiler.h>
/*
* NOTE! This ctype does not handle EOF like the standard C
* library is required to.
......@@ -23,11 +25,6 @@ extern const unsigned char _ctype[];
#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
#define iscntrl(c) ((__ismask(c)&(_C)) != 0)
static inline int __isdigit(int c)
{
return '0' <= c && c <= '9';
}
#define isdigit(c) __isdigit(c)
#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
#define islower(c) ((__ismask(c)&(_L)) != 0)
#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
......@@ -40,6 +37,16 @@ static inline int __isdigit(int c)
#define isascii(c) (((unsigned char)(c))<=0x7f)
#define toascii(c) (((unsigned char)(c))&0x7f)
#if __has_builtin(__builtin_isdigit)
#define isdigit(c) __builtin_isdigit(c)
#else
static inline int __isdigit(int c)
{
return '0' <= c && c <= '9';
}
#define isdigit(c) __isdigit(c)
#endif
static inline unsigned char __tolower(unsigned char c)
{
if (isupper(c))
......
......@@ -46,4 +46,5 @@ extern char * __must_check skip_spaces(const char *);
extern char *strim(char *);
extern void *memchr_inv(const void *start, int c, size_t bytes);
#endif /* _TOOLS_LINUX_STRING_H_ */
......@@ -517,7 +517,7 @@ __SC_COMP(__NR_settimeofday, sys_settimeofday, compat_sys_settimeofday)
__SC_3264(__NR_adjtimex, sys_adjtimex_time32, sys_adjtimex)
#endif
/* kernel/timer.c */
/* kernel/sys.c */
#define __NR_getpid 172
__SYSCALL(__NR_getpid, sys_getpid)
#define __NR_getppid 173
......
......@@ -28,4 +28,9 @@
#define _BITUL(x) (_UL(1) << (x))
#define _BITULL(x) (_ULL(1) << (x))
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
#endif /* _UAPI_LINUX_CONST_H */
......@@ -20,7 +20,6 @@
#define FSCRYPT_POLICY_FLAG_DIRECT_KEY 0x04
#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 0x08
#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32 0x10
#define FSCRYPT_POLICY_FLAGS_VALID 0x1F
/* Encryption algorithms */
#define FSCRYPT_MODE_AES_256_XTS 1
......@@ -28,7 +27,7 @@
#define FSCRYPT_MODE_AES_128_CBC 5
#define FSCRYPT_MODE_AES_128_CTS 6
#define FSCRYPT_MODE_ADIANTUM 9
#define __FSCRYPT_MODE_MAX 9
/* If adding a mode number > 9, update FSCRYPT_MODE_MAX in fscrypt_private.h */
/*
* Legacy policy version; ad-hoc KDF and no key verification.
......@@ -177,7 +176,7 @@ struct fscrypt_get_key_status_arg {
#define FS_POLICY_FLAGS_PAD_32 FSCRYPT_POLICY_FLAGS_PAD_32
#define FS_POLICY_FLAGS_PAD_MASK FSCRYPT_POLICY_FLAGS_PAD_MASK
#define FS_POLICY_FLAG_DIRECT_KEY FSCRYPT_POLICY_FLAG_DIRECT_KEY
#define FS_POLICY_FLAGS_VALID FSCRYPT_POLICY_FLAGS_VALID
#define FS_POLICY_FLAGS_VALID 0x07 /* contains old flags only */
#define FS_ENCRYPTION_MODE_INVALID 0 /* never used */
#define FS_ENCRYPTION_MODE_AES_256_XTS FSCRYPT_MODE_AES_256_XTS
#define FS_ENCRYPTION_MODE_AES_256_GCM 2 /* never used */
......
......@@ -143,8 +143,10 @@ enum perf_event_sample_format {
PERF_SAMPLE_PHYS_ADDR = 1U << 19,
PERF_SAMPLE_AUX = 1U << 20,
PERF_SAMPLE_CGROUP = 1U << 21,
PERF_SAMPLE_DATA_PAGE_SIZE = 1U << 22,
PERF_SAMPLE_CODE_PAGE_SIZE = 1U << 23,
PERF_SAMPLE_MAX = 1U << 22, /* non-ABI */
PERF_SAMPLE_MAX = 1U << 24, /* non-ABI */
__PERF_SAMPLE_CALLCHAIN_EARLY = 1ULL << 63, /* non-ABI; internal use */
};
......@@ -896,6 +898,8 @@ enum perf_event_type {
* { u64 phys_addr;} && PERF_SAMPLE_PHYS_ADDR
* { u64 size;
* char data[size]; } && PERF_SAMPLE_AUX
* { u64 data_page_size;} && PERF_SAMPLE_DATA_PAGE_SIZE
* { u64 code_page_size;} && PERF_SAMPLE_CODE_PAGE_SIZE
* };
*/
PERF_RECORD_SAMPLE = 9,
......
......@@ -247,4 +247,9 @@ struct prctl_mm_map {
#define PR_SET_IO_FLUSHER 57
#define PR_GET_IO_FLUSHER 58
/* Dispatch syscalls to a userspace handler */
#define PR_SET_SYSCALL_USER_DISPATCH 59
# define PR_SYS_DISPATCH_OFF 0
# define PR_SYS_DISPATCH_ON 1
#endif /* _LINUX_PRCTL_H */
......@@ -171,9 +171,12 @@ struct statx {
* be of use to ordinary userspace programs such as GUIs or ls rather than
* specialised tools.
*
* Note that the flags marked [I] correspond to generic FS_IOC_FLAGS
* Note that the flags marked [I] correspond to the FS_IOC_SETFLAGS flags
* semantically. Where possible, the numerical value is picked to correspond
* also.
* also. Note that the DAX attribute indicates that the file is in the CPU
* direct access state. It does not correspond to the per-inode flag that
* some filesystems support.
*
*/
#define STATX_ATTR_COMPRESSED 0x00000004 /* [I] File is compressed by the fs */
#define STATX_ATTR_IMMUTABLE 0x00000010 /* [I] File is marked immutable */
......@@ -183,7 +186,7 @@ struct statx {
#define STATX_ATTR_AUTOMOUNT 0x00001000 /* Dir: Automount trigger */
#define STATX_ATTR_MOUNT_ROOT 0x00002000 /* Root of a mount */
#define STATX_ATTR_VERITY 0x00100000 /* [I] Verity protected file */
#define STATX_ATTR_DAX 0x00002000 /* [I] File is DAX */
#define STATX_ATTR_DAX 0x00200000 /* File is currently in DAX state */
#endif /* _UAPI_LINUX_STAT_H */
......@@ -168,3 +168,61 @@ char *strreplace(char *s, char old, char new)
*s = new;
return s;
}
static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)
{
while (bytes) {
if (*start != value)
return (void *)start;
start++;
bytes--;
}
return NULL;
}
/**
* memchr_inv - Find an unmatching character in an area of memory.
* @start: The memory area
* @c: Find a character other than c
* @bytes: The size of the area.
*
* returns the address of the first character other than @c, or %NULL
* if the whole buffer contains just @c.
*/
void *memchr_inv(const void *start, int c, size_t bytes)
{
u8 value = c;
u64 value64;
unsigned int words, prefix;
if (bytes <= 16)
return check_bytes8(start, value, bytes);
value64 = value;
value64 |= value64 << 8;
value64 |= value64 << 16;
value64 |= value64 << 32;
prefix = (unsigned long)start % 8;
if (prefix) {
u8 *r;
prefix = 8 - prefix;
r = check_bytes8(start, value, prefix);
if (r)
return r;
start += prefix;
bytes -= prefix;
}
words = bytes / 8;
while (words) {
if (*(u64 *)start != value64)
return check_bytes8(start, value, 8);
start += 8;
words--;
}
return check_bytes8(start, value, bytes % 8);
}
......@@ -11,6 +11,7 @@
d create a debug log
f synthesize first level cache events
m synthesize last level cache events
M synthesize memory events
t synthesize TLB events
a synthesize remote access events
g synthesize a call chain (use with i or x)
......
......@@ -138,7 +138,7 @@ If you want to add or modify several config items, you can do like
To modify the sort order of report functionality in user config file(i.e. `~/.perfconfig`), do
% perf config --user report sort-order=srcline
% perf config --user report.sort-order=srcline
To change colors of selected line to other foreground and background colors
in system config file (i.e. `$(sysconf)/perfconfig`), do
......
......@@ -293,6 +293,9 @@ OPTIONS
--phys-data::
Record the sample physical addresses.
--data-page-size::
Record the sampled data address data page size.
-T::
--timestamp::
Record the sample timestamps. Use it with 'perf report -D' to see the
......@@ -634,11 +637,17 @@ endif::HAVE_LIBPFM[]
--control=fifo:ctl-fifo[,ack-fifo]::
--control=fd:ctl-fd[,ack-fd]::
ctl-fifo / ack-fifo are opened and used as ctl-fd / ack-fd as follows.
Listen on ctl-fd descriptor for command to control measurement ('enable': enable events,
'disable': disable events, 'snapshot': AUX area tracing snapshot). Measurements can be
started with events disabled using --delay=-1 option. Optionally send control command
completion ('ack\n') to ack-fd descriptor to synchronize with the controlling process.
Example of bash shell script to enable and disable events during measurements:
Listen on ctl-fd descriptor for command to control measurement.
Available commands:
'enable' : enable events
'disable' : disable events
'snapshot': AUX area tracing snapshot).
Measurements can be started with events disabled using --delay=-1 option. Optionally
send control command completion ('ack\n') to ack-fd descriptor to synchronize with the
controlling process. Example of bash shell script to enable and disable events during
measurements:
#!/bin/bash
......
......@@ -150,6 +150,7 @@ OPTIONS
- snoop: type of snoop (if any) for the data at the time of the sample
- dcacheline: the cacheline the data address is on at the time of the sample
- phys_daddr: physical address of data being executed on at the time of sample
- data_page_size: the data page size of data being executed on at the time of sample
And the default sort keys are changed to local_weight, mem, sym, dso,
symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'.
......
......@@ -116,8 +116,9 @@ OPTIONS
--fields::
Comma separated list of fields to print. Options are:
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
srcline, period, iregs, uregs, brstack, brstacksym, flags, bpf-output, brstackinsn,
brstackoff, callindent, insn, insnlen, synth, phys_addr, metric, misc, srccode, ipc.
srcline, period, iregs, uregs, brstack, brstacksym, flags, bpf-output,
brstackinsn, brstackoff, callindent, insn, insnlen, synth, phys_addr,
metric, misc, srccode, ipc, data_page_size.
Field list can be prepended with the type, trace, sw or hw,
to indicate to which event type the field list applies.
e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace
......
......@@ -168,8 +168,9 @@ command line can be used: 'perf stat -e cycles -G cgroup_name -a -e cycles'.
--for-each-cgroup name::
Expand event list for each cgroup in "name" (allow multiple cgroups separated
by comma). This has same effect that repeating -e option and -G option for
each event x name. This option cannot be used with -G/--cgroup option.
by comma). It also support regex patterns to match multiple groups. This has same
effect that repeating -e option and -G option for each event x name. This option
cannot be used with -G/--cgroup option.
-o file::
--output file::
......@@ -316,6 +317,10 @@ small group that need not have multiplexing is lowered. This option
forbids the event merging logic from sharing events between groups and
may be used to increase accuracy in this case.
--quiet::
Don't print output. This is useful with perf stat record below to only
write data to the perf.data file.
STAT RECORD
-----------
Stores stat data into perf data file.
......
......@@ -395,7 +395,7 @@ static int cs_etm_recording_options(struct auxtrace_record *itr,
* To obtain the auxtrace buffer file descriptor, the auxtrace
* event must come first.
*/
perf_evlist__to_front(evlist, cs_etm_evsel);
evlist__to_front(evlist, cs_etm_evsel);
/*
* In the case of per-cpu mmaps, we need the CPU on the
......@@ -420,7 +420,7 @@ static int cs_etm_recording_options(struct auxtrace_record *itr,
goto out;
tracking_evsel = evlist__last(evlist);
perf_evlist__set_tracking_event(evlist, tracking_evsel);
evlist__set_tracking_event(evlist, tracking_evsel);
tracking_evsel->core.attr.freq = 0;
tracking_evsel->core.attr.sample_period = 1;
......
......@@ -4,6 +4,7 @@ PERF_HAVE_DWARF_REGS := 1
endif
PERF_HAVE_JITDUMP := 1
PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
HAVE_KVM_STAT_SUPPORT := 1
#
# Syscall table generation for perf
......
......@@ -2,6 +2,7 @@ perf-y += header.o
perf-y += machine.o
perf-y += perf_regs.o
perf-y += tsc.o
perf-y += kvm-stat.o
perf-$(CONFIG_DWARF) += dwarf-regs.o
perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
......@@ -9,4 +10,4 @@ perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
perf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \
../../arm/util/auxtrace.o \
../../arm/util/cs-etm.o \
arm-spe.o
arm-spe.o mem-events.o
......@@ -118,7 +118,7 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
* To obtain the auxtrace buffer file descriptor, the auxtrace event
* must come first.
*/
perf_evlist__to_front(evlist, arm_spe_evsel);
evlist__to_front(evlist, arm_spe_evsel);
evsel__set_sample_bit(arm_spe_evsel, CPU);
evsel__set_sample_bit(arm_spe_evsel, TIME);
......@@ -130,7 +130,7 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
return err;
tracking_evsel = evlist__last(evlist);
perf_evlist__set_tracking_event(evlist, tracking_evsel);
evlist__set_tracking_event(evlist, tracking_evsel);
tracking_evsel->core.attr.freq = 0;
tracking_evsel->core.attr.sample_period = 1;
......
// SPDX-License-Identifier: GPL-2.0
#ifndef ARCH_PERF_ARM64_EXCEPTION_TYPES_H
#define ARCH_PERF_ARM64_EXCEPTION_TYPES_H
/* Per asm/virt.h */
#define HVC_STUB_ERR 0xbadca11
/* Per asm/kvm_asm.h */
#define ARM_EXCEPTION_IRQ 0
#define ARM_EXCEPTION_EL1_SERROR 1
#define ARM_EXCEPTION_TRAP 2
#define ARM_EXCEPTION_IL 3
/* The hyp-stub will return this for any kvm_call_hyp() call */
#define ARM_EXCEPTION_HYP_GONE HVC_STUB_ERR
#define kvm_arm_exception_type \
{ARM_EXCEPTION_IRQ, "IRQ" }, \
{ARM_EXCEPTION_EL1_SERROR, "SERROR" }, \
{ARM_EXCEPTION_TRAP, "TRAP" }, \
{ARM_EXCEPTION_IL, "ILLEGAL" }, \
{ARM_EXCEPTION_HYP_GONE, "HYP_GONE" }
/* Per asm/esr.h */
#define ESR_ELx_EC_UNKNOWN (0x00)
#define ESR_ELx_EC_WFx (0x01)
/* Unallocated EC: 0x02 */
#define ESR_ELx_EC_CP15_32 (0x03)
#define ESR_ELx_EC_CP15_64 (0x04)
#define ESR_ELx_EC_CP14_MR (0x05)
#define ESR_ELx_EC_CP14_LS (0x06)
#define ESR_ELx_EC_FP_ASIMD (0x07)
#define ESR_ELx_EC_CP10_ID (0x08) /* EL2 only */
#define ESR_ELx_EC_PAC (0x09) /* EL2 and above */
/* Unallocated EC: 0x0A - 0x0B */
#define ESR_ELx_EC_CP14_64 (0x0C)
/* Unallocated EC: 0x0d */
#define ESR_ELx_EC_ILL (0x0E)
/* Unallocated EC: 0x0F - 0x10 */
#define ESR_ELx_EC_SVC32 (0x11)
#define ESR_ELx_EC_HVC32 (0x12) /* EL2 only */
#define ESR_ELx_EC_SMC32 (0x13) /* EL2 and above */
/* Unallocated EC: 0x14 */
#define ESR_ELx_EC_SVC64 (0x15)
#define ESR_ELx_EC_HVC64 (0x16) /* EL2 and above */
#define ESR_ELx_EC_SMC64 (0x17) /* EL2 and above */
#define ESR_ELx_EC_SYS64 (0x18)
#define ESR_ELx_EC_SVE (0x19)
#define ESR_ELx_EC_ERET (0x1a) /* EL2 only */
/* Unallocated EC: 0x1b - 0x1E */
#define ESR_ELx_EC_IMP_DEF (0x1f) /* EL3 only */
#define ESR_ELx_EC_IABT_LOW (0x20)
#define ESR_ELx_EC_IABT_CUR (0x21)
#define ESR_ELx_EC_PC_ALIGN (0x22)
/* Unallocated EC: 0x23 */
#define ESR_ELx_EC_DABT_LOW (0x24)
#define ESR_ELx_EC_DABT_CUR (0x25)
#define ESR_ELx_EC_SP_ALIGN (0x26)
/* Unallocated EC: 0x27 */
#define ESR_ELx_EC_FP_EXC32 (0x28)
/* Unallocated EC: 0x29 - 0x2B */
#define ESR_ELx_EC_FP_EXC64 (0x2C)
/* Unallocated EC: 0x2D - 0x2E */
#define ESR_ELx_EC_SERROR (0x2F)
#define ESR_ELx_EC_BREAKPT_LOW (0x30)
#define ESR_ELx_EC_BREAKPT_CUR (0x31)
#define ESR_ELx_EC_SOFTSTP_LOW (0x32)
#define ESR_ELx_EC_SOFTSTP_CUR (0x33)
#define ESR_ELx_EC_WATCHPT_LOW (0x34)
#define ESR_ELx_EC_WATCHPT_CUR (0x35)
/* Unallocated EC: 0x36 - 0x37 */
#define ESR_ELx_EC_BKPT32 (0x38)
/* Unallocated EC: 0x39 */
#define ESR_ELx_EC_VECTOR32 (0x3A) /* EL2 only */
/* Unallocated EC: 0x3B */
#define ESR_ELx_EC_BRK64 (0x3C)
/* Unallocated EC: 0x3D - 0x3F */
#define ESR_ELx_EC_MAX (0x3F)
#define ECN(x) { ESR_ELx_EC_##x, #x }
#define kvm_arm_exception_class \
ECN(UNKNOWN), ECN(WFx), ECN(CP15_32), ECN(CP15_64), ECN(CP14_MR), \
ECN(CP14_LS), ECN(FP_ASIMD), ECN(CP10_ID), ECN(PAC), ECN(CP14_64), \
ECN(SVC64), ECN(HVC64), ECN(SMC64), ECN(SYS64), ECN(SVE), \
ECN(IMP_DEF), ECN(IABT_LOW), ECN(IABT_CUR), \
ECN(PC_ALIGN), ECN(DABT_LOW), ECN(DABT_CUR), \
ECN(SP_ALIGN), ECN(FP_EXC32), ECN(FP_EXC64), ECN(SERROR), \
ECN(BREAKPT_LOW), ECN(BREAKPT_CUR), ECN(SOFTSTP_LOW), \
ECN(SOFTSTP_CUR), ECN(WATCHPT_LOW), ECN(WATCHPT_CUR), \
ECN(BKPT32), ECN(VECTOR32), ECN(BRK64)
#endif /* ARCH_PERF_ARM64_EXCEPTION_TYPES_H */
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
#include <memory.h>
#include "../../util/evsel.h"
#include "../../util/kvm-stat.h"
#include "arm64_exception_types.h"
#include "debug.h"
define_exit_reasons_table(arm64_exit_reasons, kvm_arm_exception_type);
define_exit_reasons_table(arm64_trap_exit_reasons, kvm_arm_exception_class);
const char *kvm_trap_exit_reason = "esr_ec";
const char *vcpu_id_str = "id";
const int decode_str_len = 20;
const char *kvm_exit_reason = "ret";
const char *kvm_entry_trace = "kvm:kvm_entry";
const char *kvm_exit_trace = "kvm:kvm_exit";
const char *kvm_events_tp[] = {
"kvm:kvm_entry",
"kvm:kvm_exit",
NULL,
};
static void event_get_key(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
key->info = 0;
key->key = evsel__intval(evsel, sample, kvm_exit_reason);
key->exit_reasons = arm64_exit_reasons;
/*
* TRAP exceptions carry exception class info in esr_ec field
* and, hence, we need to use a different exit_reasons table to
* properly decode event's est_ec.
*/
if (key->key == ARM_EXCEPTION_TRAP) {
key->key = evsel__intval(evsel, sample, kvm_trap_exit_reason);
key->exit_reasons = arm64_trap_exit_reasons;
}
}
static bool event_begin(struct evsel *evsel,
struct perf_sample *sample __maybe_unused,
struct event_key *key __maybe_unused)
{
return !strcmp(evsel->name, kvm_entry_trace);
}
static bool event_end(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
if (!strcmp(evsel->name, kvm_exit_trace)) {
event_get_key(evsel, sample, key);
return true;
}
return false;
}
static struct kvm_events_ops exit_events = {
.is_begin_event = event_begin,
.is_end_event = event_end,
.decode_key = exit_event_decode_key,
.name = "VM-EXIT"
};
struct kvm_reg_events_ops kvm_reg_events_ops[] = {
{
.name = "vmexit",
.ops = &exit_events,
},
{ NULL },
};
const char * const kvm_skip_events[] = {
NULL,
};
int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid __maybe_unused)
{
kvm->exit_reasons_isa = "arm64";
return 0;
}
// SPDX-License-Identifier: GPL-2.0
#include "map_symbol.h"
#include "mem-events.h"
#define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
static struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
E("spe-load", "arm_spe_0/ts_enable=1,load_filter=1,store_filter=0,min_latency=%u/", "arm_spe_0"),
E("spe-store", "arm_spe_0/ts_enable=1,load_filter=0,store_filter=1/", "arm_spe_0"),
E("spe-ldst", "arm_spe_0/ts_enable=1,load_filter=1,store_filter=1,min_latency=%u/", "arm_spe_0"),
};
static char mem_ev_name[100];
struct perf_mem_event *perf_mem_events__ptr(int i)
{
if (i >= PERF_MEM_EVENTS__MAX)
return NULL;
return &perf_mem_events[i];
}
char *perf_mem_events__name(int i)
{
struct perf_mem_event *e = perf_mem_events__ptr(i);
if (i >= PERF_MEM_EVENTS__MAX)
return NULL;
if (i == PERF_MEM_EVENTS__LOAD || i == PERF_MEM_EVENTS__LOAD_STORE)
scnprintf(mem_ev_name, sizeof(mem_ev_name),
e->name, perf_mem_events__loads_ldlat);
else /* PERF_MEM_EVENTS__STORE */
scnprintf(mem_ev_name, sizeof(mem_ev_name), e->name);
return mem_ev_name;
}
......@@ -2,5 +2,38 @@
#include "../../../util/perf_regs.h"
const struct sample_reg sample_reg_masks[] = {
SMPL_REG(x0, PERF_REG_ARM64_X0),
SMPL_REG(x1, PERF_REG_ARM64_X1),
SMPL_REG(x2, PERF_REG_ARM64_X2),
SMPL_REG(x3, PERF_REG_ARM64_X3),
SMPL_REG(x4, PERF_REG_ARM64_X4),
SMPL_REG(x5, PERF_REG_ARM64_X5),
SMPL_REG(x6, PERF_REG_ARM64_X6),
SMPL_REG(x7, PERF_REG_ARM64_X7),
SMPL_REG(x8, PERF_REG_ARM64_X8),
SMPL_REG(x9, PERF_REG_ARM64_X9),
SMPL_REG(x10, PERF_REG_ARM64_X10),
SMPL_REG(x11, PERF_REG_ARM64_X11),
SMPL_REG(x12, PERF_REG_ARM64_X12),
SMPL_REG(x13, PERF_REG_ARM64_X13),
SMPL_REG(x14, PERF_REG_ARM64_X14),
SMPL_REG(x15, PERF_REG_ARM64_X15),
SMPL_REG(x16, PERF_REG_ARM64_X16),
SMPL_REG(x17, PERF_REG_ARM64_X17),
SMPL_REG(x18, PERF_REG_ARM64_X18),
SMPL_REG(x19, PERF_REG_ARM64_X19),
SMPL_REG(x20, PERF_REG_ARM64_X20),
SMPL_REG(x21, PERF_REG_ARM64_X21),
SMPL_REG(x22, PERF_REG_ARM64_X22),
SMPL_REG(x23, PERF_REG_ARM64_X23),
SMPL_REG(x24, PERF_REG_ARM64_X24),
SMPL_REG(x25, PERF_REG_ARM64_X25),
SMPL_REG(x26, PERF_REG_ARM64_X26),
SMPL_REG(x27, PERF_REG_ARM64_X27),
SMPL_REG(x28, PERF_REG_ARM64_X28),
SMPL_REG(x29, PERF_REG_ARM64_X29),
SMPL_REG(lr, PERF_REG_ARM64_LR),
SMPL_REG(sp, PERF_REG_ARM64_SP),
SMPL_REG(pc, PERF_REG_ARM64_PC),
SMPL_REG_END
};
// SPDX-License-Identifier: GPL-2.0
static
struct ins_ops *mips__associate_ins_ops(struct arch *arch, const char *name)
{
struct ins_ops *ops = NULL;
if (!strncmp(name, "bal", 3) ||
!strncmp(name, "bgezal", 6) ||
!strncmp(name, "bltzal", 6) ||
!strncmp(name, "bgtzal", 6) ||
!strncmp(name, "blezal", 6) ||
!strncmp(name, "beqzal", 6) ||
!strncmp(name, "bnezal", 6) ||
!strncmp(name, "bgtzl", 5) ||
!strncmp(name, "bltzl", 5) ||
!strncmp(name, "bgezl", 5) ||
!strncmp(name, "blezl", 5) ||
!strncmp(name, "jialc", 5) ||
!strncmp(name, "beql", 4) ||
!strncmp(name, "bnel", 4) ||
!strncmp(name, "jal", 3))
ops = &call_ops;
else if (!strncmp(name, "jr", 2))
ops = &ret_ops;
else if (name[0] == 'j' || name[0] == 'b')
ops = &jump_ops;
else
return NULL;
arch__associate_ins_ops(arch, name, ops);
return ops;
}
static
int mips__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
{
if (!arch->initialized) {
arch->associate_instruction_ops = mips__associate_ins_ops;
arch->initialized = true;
arch->objdump.comment_char = '#';
}
return 0;
}
......@@ -7,7 +7,6 @@ struct test;
/* Tests */
int test__rdpmc(struct test *test __maybe_unused, int subtest);
int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest);
int test__insn_x86(struct test *test __maybe_unused, int subtest);
int test__intel_pt_pkt_decoder(struct test *test, int subtest);
int test__bp_modify(struct test *test, int subtest);
......
......@@ -3,6 +3,5 @@ perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
perf-y += arch-tests.o
perf-y += rdpmc.o
perf-y += perf-time-to-tsc.o
perf-$(CONFIG_AUXTRACE) += insn-x86.o intel-pt-pkt-decoder-test.o
perf-$(CONFIG_X86_64) += bp-modify.o
......@@ -8,10 +8,6 @@ struct test arch_tests[] = {
.desc = "x86 rdpmc",
.func = test__rdpmc,
},
{
.desc = "Convert perf time to TSC",
.func = test__perf_time_to_tsc,
},
#ifdef HAVE_DWARF_UNWIND_SUPPORT
{
.desc = "DWARF unwind",
......
......@@ -52,7 +52,7 @@ int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, int subt
evlist = evlist__new();
if (!evlist) {
pr_debug("perf_evlist__new failed\n");
pr_debug("evlist__new failed\n");
return TEST_FAIL;
}
......
......@@ -218,7 +218,7 @@ static int intel_bts_recording_options(struct auxtrace_record *itr,
* To obtain the auxtrace buffer file descriptor, the auxtrace event
* must come first.
*/
perf_evlist__to_front(evlist, intel_bts_evsel);
evlist__to_front(evlist, intel_bts_evsel);
/*
* In the case of per-cpu mmaps, we need the CPU on the
* AUX event.
......@@ -238,7 +238,7 @@ static int intel_bts_recording_options(struct auxtrace_record *itr,
tracking_evsel = evlist__last(evlist);
perf_evlist__set_tracking_event(evlist, tracking_evsel);
evlist__set_tracking_event(evlist, tracking_evsel);
tracking_evsel->core.attr.freq = 0;
tracking_evsel->core.attr.sample_period = 1;
......
......@@ -416,7 +416,7 @@ static int intel_pt_track_switches(struct evlist *evlist)
struct evsel *evsel;
int err;
if (!perf_evlist__can_select_event(evlist, sched_switch))
if (!evlist__can_select_event(evlist, sched_switch))
return -EPERM;
err = parse_events(evlist, sched_switch, NULL);
......@@ -846,7 +846,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
* To obtain the auxtrace buffer file descriptor, the auxtrace
* event must come first.
*/
perf_evlist__to_front(evlist, intel_pt_evsel);
evlist__to_front(evlist, intel_pt_evsel);
/*
* In the case of per-cpu mmaps, we need the CPU on the
* AUX event.
......@@ -865,7 +865,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
tracking_evsel = evlist__last(evlist);
perf_evlist__set_tracking_event(evlist, tracking_evsel);
evlist__set_tracking_event(evlist, tracking_evsel);
tracking_evsel->core.attr.freq = 0;
tracking_evsel->core.attr.sample_period = 1;
......
......@@ -412,7 +412,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
if (dump_trace) {
perf_session__fprintf_nr_events(session, stdout);
perf_evlist__fprintf_nr_events(session->evlist, stdout);
evlist__fprintf_nr_events(session->evlist, stdout);
goto out;
}
......@@ -598,7 +598,7 @@ int cmd_annotate(int argc, const char **argv)
HEADER_BRANCH_STACK);
if (annotate.group_set)
perf_evlist__force_leader(annotate.session->evlist);
evlist__force_leader(annotate.session->evlist);
ret = symbol__annotation_init();
if (ret < 0)
......
......@@ -369,6 +369,10 @@ static struct perf_c2c c2c = {
.exit = perf_event__process_exit,
.fork = perf_event__process_fork,
.lost = perf_event__process_lost,
.attr = perf_event__process_attr,
.auxtrace_info = perf_event__process_auxtrace_info,
.auxtrace = perf_event__process_auxtrace,
.auxtrace_error = perf_event__process_auxtrace_error,
.ordered_events = true,
.ordering_requires_timestamps = true,
},
......@@ -2678,6 +2682,12 @@ static int setup_coalesce(const char *coalesce, bool no_source)
static int perf_c2c__report(int argc, const char **argv)
{
struct itrace_synth_opts itrace_synth_opts = {
.set = true,
.mem = true, /* Only enable memory event */
.default_no_sample = true,
};
struct perf_session *session;
struct ui_progress prog;
struct perf_data data = {
......@@ -2757,6 +2767,8 @@ static int perf_c2c__report(int argc, const char **argv)
goto out;
}
session->itrace_synth_opts = &itrace_synth_opts;
err = setup_nodes(session);
if (err) {
pr_err("Failed setup nodes\n");
......@@ -2867,6 +2879,7 @@ static int perf_c2c__record(int argc, const char **argv)
int ret;
bool all_user = false, all_kernel = false;
bool event_set = false;
struct perf_mem_event *e;
struct option options[] = {
OPT_CALLBACK('e', "event", &event_set, "event",
"event selector. Use 'perf c2c record -e list' to list available events",
......@@ -2894,11 +2907,24 @@ static int perf_c2c__record(int argc, const char **argv)
rec_argv[i++] = "record";
if (!event_set) {
perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true;
perf_mem_events[PERF_MEM_EVENTS__STORE].record = true;
e = perf_mem_events__ptr(PERF_MEM_EVENTS__LOAD_STORE);
/*
* The load and store operations are required, use the event
* PERF_MEM_EVENTS__LOAD_STORE if it is supported.
*/
if (e->tag) {
e->record = true;
} else {
e = perf_mem_events__ptr(PERF_MEM_EVENTS__LOAD);
e->record = true;
e = perf_mem_events__ptr(PERF_MEM_EVENTS__STORE);
e->record = true;
}
}
if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record)
e = perf_mem_events__ptr(PERF_MEM_EVENTS__LOAD);
if (e->record)
rec_argv[i++] = "-W";
rec_argv[i++] = "-d";
......@@ -2906,12 +2932,13 @@ static int perf_c2c__record(int argc, const char **argv)
rec_argv[i++] = "--sample-cpu";
for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
if (!perf_mem_events[j].record)
e = perf_mem_events__ptr(j);
if (!e->record)
continue;
if (!perf_mem_events[j].supported) {
if (!e->supported) {
pr_err("failed: event '%s' not supported\n",
perf_mem_events[j].name);
perf_mem_events__name(j));
free(rec_argv);
return -1;
}
......
......@@ -494,7 +494,7 @@ static struct evsel *evsel_match(struct evsel *evsel,
return NULL;
}
static void perf_evlist__collapse_resort(struct evlist *evlist)
static void evlist__collapse_resort(struct evlist *evlist)
{
struct evsel *evsel;
......@@ -1214,7 +1214,7 @@ static int __cmd_diff(void)
goto out_delete;
}
perf_evlist__collapse_resort(d->session->evlist);
evlist__collapse_resort(d->session->evlist);
if (pdiff.ptime_range)
zfree(&pdiff.ptime_range);
......
......@@ -17,6 +17,14 @@
#include "util/data.h"
#include "util/debug.h"
#include <linux/err.h>
#include "util/tool.h"
static int process_header_feature(struct perf_session *session __maybe_unused,
union perf_event *event __maybe_unused)
{
session_done = 1;
return 0;
}
static int __cmd_evlist(const char *file_name, struct perf_attr_details *details)
{
......@@ -27,12 +35,20 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
.mode = PERF_DATA_MODE_READ,
.force = details->force,
};
struct perf_tool tool = {
/* only needed for pipe mode */
.attr = perf_event__process_attr,
.feature = process_header_feature,
};
bool has_tracepoint = false;
session = perf_session__new(&data, 0, NULL);
session = perf_session__new(&data, 0, &tool);
if (IS_ERR(session))
return PTR_ERR(session);
if (data.is_pipe)
perf_session__process_events(session);
evlist__for_each_entry(session->evlist, pos) {
evsel__fprintf(pos, details, stdout);
......
......@@ -67,7 +67,7 @@ static void sig_handler(int sig __maybe_unused)
}
/*
* perf_evlist__prepare_workload will send a SIGUSR1 if the fork fails, since
* evlist__prepare_workload will send a SIGUSR1 if the fork fails, since
* we asked by setting its exec_error to the function below,
* ftrace__workload_exec_failed_signal.
*
......@@ -600,9 +600,8 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
if (write_tracing_file("trace", "0") < 0)
goto out;
if (argc && perf_evlist__prepare_workload(ftrace->evlist,
&ftrace->target, argv, false,
ftrace__workload_exec_failed_signal) < 0) {
if (argc && evlist__prepare_workload(ftrace->evlist, &ftrace->target, argv, false,
ftrace__workload_exec_failed_signal) < 0) {
goto out;
}
......@@ -644,7 +643,7 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
}
}
perf_evlist__start_workload(ftrace->evlist);
evlist__start_workload(ftrace->evlist);
if (ftrace->initial_delay) {
usleep(ftrace->initial_delay * 1000);
......@@ -958,7 +957,7 @@ int cmd_ftrace(int argc, const char **argv)
goto out_delete_filters;
}
ret = perf_evlist__create_maps(ftrace.evlist, &ftrace.target);
ret = evlist__create_maps(ftrace.evlist, &ftrace.target);
if (ret < 0)
goto out_delete_evlist;
......
......@@ -843,10 +843,12 @@ int cmd_inject(int argc, const char **argv)
.output = {
.path = "-",
.mode = PERF_DATA_MODE_WRITE,
.use_stdio = true,
},
};
struct perf_data data = {
.mode = PERF_DATA_MODE_READ,
.use_stdio = true,
};
int ret;
......
......@@ -1960,18 +1960,15 @@ int cmd_kmem(int argc, const char **argv)
ret = -1;
if (kmem_slab) {
if (!perf_evlist__find_tracepoint_by_name(session->evlist,
"kmem:kmalloc")) {
if (!evlist__find_tracepoint_by_name(session->evlist, "kmem:kmalloc")) {
pr_err(errmsg, "slab", "slab");
goto out_delete;
}
}
if (kmem_page) {
struct evsel *evsel;
struct evsel *evsel = evlist__find_tracepoint_by_name(session->evlist, "kmem:mm_page_alloc");
evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
"kmem:mm_page_alloc");
if (evsel == NULL) {
pr_err(errmsg, "page", "page");
goto out_delete;
......
......@@ -764,7 +764,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
return (err == -EAGAIN) ? 0 : -1;
while ((event = perf_mmap__read_event(&md->core)) != NULL) {
err = perf_evlist__parse_sample_timestamp(evlist, event, &timestamp);
err = evlist__parse_sample_timestamp(evlist, event, &timestamp);
if (err) {
perf_mmap__consume(&md->core);
pr_err("Failed to parse sample\n");
......@@ -1022,7 +1022,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
struct evlist *evlist = kvm->evlist;
char sbuf[STRERR_BUFSIZE];
perf_evlist__config(evlist, &kvm->opts, NULL);
evlist__config(evlist, &kvm->opts, NULL);
/*
* Note: exclude_{guest,host} do not apply here.
......@@ -1349,8 +1349,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
"record events on existing process id"),
OPT_CALLBACK('m', "mmap-pages", &kvm->opts.mmap_pages, "pages",
"number of mmap data pages",
perf_evlist__parse_mmap_pages),
"number of mmap data pages", evlist__parse_mmap_pages),
OPT_INCR('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"),
OPT_BOOLEAN('a', "all-cpus", &kvm->opts.target.system_wide,
......@@ -1442,7 +1441,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
goto out;
}
if (perf_evlist__create_maps(kvm->evlist, &kvm->opts.target) < 0)
if (evlist__create_maps(kvm->evlist, &kvm->opts.target) < 0)
usage_with_options(live_usage, live_options);
/*
......
......@@ -7,6 +7,7 @@
#include "perf.h"
#include <subcmd/parse-options.h>
#include "util/auxtrace.h"
#include "util/trace-event.h"
#include "util/tool.h"
#include "util/session.h"
......@@ -64,6 +65,7 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
const char **rec_argv;
int ret;
bool all_user = false, all_kernel = false;
struct perf_mem_event *e;
struct option options[] = {
OPT_CALLBACK('e', "event", &mem, "event",
"event selector. use 'perf mem record -e list' to list available events",
......@@ -76,6 +78,11 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
OPT_END()
};
if (perf_mem_events__init()) {
pr_err("failed: memory events not supported\n");
return -1;
}
argc = parse_options(argc, argv, options, record_mem_usage,
PARSE_OPT_KEEP_UNKNOWN);
......@@ -86,13 +93,30 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
rec_argv[i++] = "record";
if (mem->operation & MEM_OPERATION_LOAD)
perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true;
e = perf_mem_events__ptr(PERF_MEM_EVENTS__LOAD_STORE);
if (mem->operation & MEM_OPERATION_STORE)
perf_mem_events[PERF_MEM_EVENTS__STORE].record = true;
/*
* The load and store operations are required, use the event
* PERF_MEM_EVENTS__LOAD_STORE if it is supported.
*/
if (e->tag &&
(mem->operation & MEM_OPERATION_LOAD) &&
(mem->operation & MEM_OPERATION_STORE)) {
e->record = true;
} else {
if (mem->operation & MEM_OPERATION_LOAD) {
e = perf_mem_events__ptr(PERF_MEM_EVENTS__LOAD);
e->record = true;
}
if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record)
if (mem->operation & MEM_OPERATION_STORE) {
e = perf_mem_events__ptr(PERF_MEM_EVENTS__STORE);
e->record = true;
}
}
e = perf_mem_events__ptr(PERF_MEM_EVENTS__LOAD);
if (e->record)
rec_argv[i++] = "-W";
rec_argv[i++] = "-d";
......@@ -101,10 +125,11 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
rec_argv[i++] = "--phys-data";
for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
if (!perf_mem_events[j].record)
e = perf_mem_events__ptr(j);
if (!e->record)
continue;
if (!perf_mem_events[j].supported) {
if (!e->supported) {
pr_err("failed: event '%s' not supported\n",
perf_mem_events__name(j));
free(rec_argv);
......@@ -231,6 +256,12 @@ static int process_sample_event(struct perf_tool *tool,
static int report_raw_events(struct perf_mem *mem)
{
struct itrace_synth_opts itrace_synth_opts = {
.set = true,
.mem = true, /* Only enable memory event */
.default_no_sample = true,
};
struct perf_data data = {
.path = input_name,
.mode = PERF_DATA_MODE_READ,
......@@ -243,6 +274,8 @@ static int report_raw_events(struct perf_mem *mem)
if (IS_ERR(session))
return PTR_ERR(session);
session->itrace_synth_opts = &itrace_synth_opts;
if (mem->cpu_list) {
ret = perf_session__cpu_bitmap(session, mem->cpu_list,
mem->cpu_bitmap);
......@@ -265,11 +298,35 @@ static int report_raw_events(struct perf_mem *mem)
perf_session__delete(session);
return ret;
}
static char *get_sort_order(struct perf_mem *mem)
{
bool has_extra_options = mem->phys_addr ? true : false;
char sort[128];
/*
* there is no weight (cost) associated with stores, so don't print
* the column
*/
if (!(mem->operation & MEM_OPERATION_LOAD)) {
strcpy(sort, "--sort=mem,sym,dso,symbol_daddr,"
"dso_daddr,tlb,locked");
} else if (has_extra_options) {
strcpy(sort, "--sort=local_weight,mem,sym,dso,symbol_daddr,"
"dso_daddr,snoop,tlb,locked");
} else
return NULL;
if (mem->phys_addr)
strcat(sort, ",phys_daddr");
return strdup(sort);
}
static int report_events(int argc, const char **argv, struct perf_mem *mem)
{
const char **rep_argv;
int ret, i = 0, j, rep_argc;
char *new_sort_order;
if (mem->dump_raw)
return report_raw_events(mem);
......@@ -283,20 +340,9 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem)
rep_argv[i++] = "--mem-mode";
rep_argv[i++] = "-n"; /* display number of samples */
/*
* there is no weight (cost) associated with stores, so don't print
* the column
*/
if (!(mem->operation & MEM_OPERATION_LOAD)) {
if (mem->phys_addr)
rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr,"
"dso_daddr,tlb,locked,phys_daddr";
else
rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr,"
"dso_daddr,tlb,locked";
} else if (mem->phys_addr)
rep_argv[i++] = "--sort=local_weight,mem,sym,dso,symbol_daddr,"
"dso_daddr,snoop,tlb,locked,phys_daddr";
new_sort_order = get_sort_order(mem);
if (new_sort_order)
rep_argv[i++] = new_sort_order;
for (j = 1; j < argc; j++, i++)
rep_argv[i] = argv[j];
......@@ -386,8 +432,12 @@ int cmd_mem(int argc, const char **argv)
.comm = perf_event__process_comm,
.lost = perf_event__process_lost,
.fork = perf_event__process_fork,
.attr = perf_event__process_attr,
.build_id = perf_event__process_build_id,
.namespaces = perf_event__process_namespaces,
.auxtrace_info = perf_event__process_auxtrace_info,
.auxtrace = perf_event__process_auxtrace,
.auxtrace_error = perf_event__process_auxtrace_error,
.ordered_events = true,
},
.input_name = "perf.data",
......@@ -422,11 +472,6 @@ int cmd_mem(int argc, const char **argv)
NULL
};
if (perf_mem_events__init()) {
pr_err("failed: memory events not supported\n");
return -1;
}
argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands,
mem_usage, PARSE_OPT_KEEP_UNKNOWN);
......
......@@ -891,13 +891,13 @@ static int record__open(struct record *rec)
* event synthesis.
*/
if (opts->initial_delay || target__has_cpu(&opts->target)) {
pos = perf_evlist__get_tracking_event(evlist);
pos = evlist__get_tracking_event(evlist);
if (!evsel__is_dummy_event(pos)) {
/* Set up dummy event. */
if (evlist__add_dummy(evlist))
return -ENOMEM;
pos = evlist__last(evlist);
perf_evlist__set_tracking_event(evlist, pos);
evlist__set_tracking_event(evlist, pos);
}
/*
......@@ -910,7 +910,7 @@ static int record__open(struct record *rec)
pos->immediate = 1;
}
perf_evlist__config(evlist, opts, &callchain_param);
evlist__config(evlist, opts, &callchain_param);
evlist__for_each_entry(evlist, pos) {
try_again:
......@@ -923,7 +923,7 @@ static int record__open(struct record *rec)
if ((errno == EINVAL || errno == EBADF) &&
pos->leader != pos &&
pos->weak_group) {
pos = perf_evlist__reset_weak_group(evlist, pos, true);
pos = evlist__reset_weak_group(evlist, pos, true);
goto try_again;
}
rc = -errno;
......@@ -935,7 +935,7 @@ static int record__open(struct record *rec)
pos->supported = true;
}
if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel(evlist)) {
if (symbol_conf.kptr_restrict && !evlist__exclude_kernel(evlist)) {
pr_warning(
"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
"check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n"
......@@ -946,7 +946,7 @@ static int record__open(struct record *rec)
"even with a suitable vmlinux or kallsyms file.\n\n");
}
if (perf_evlist__apply_filters(evlist, &pos)) {
if (evlist__apply_filters(evlist, &pos)) {
pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
pos->filter, evsel__name(pos), errno,
str_error_r(errno, msg, sizeof(msg)));
......@@ -1166,7 +1166,7 @@ static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist,
rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));
if (overwrite)
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
out:
return rc;
}
......@@ -1333,7 +1333,7 @@ record__switch_output(struct record *rec, bool at_exit)
static volatile int workload_exec_errno;
/*
* perf_evlist__prepare_workload will send a SIGUSR1
* evlist__prepare_workload will send a SIGUSR1
* if the fork fails, since we asked by setting its
* want_signal to true.
*/
......@@ -1349,8 +1349,7 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
static void snapshot_sig_handler(int sig);
static void alarm_sig_handler(int sig);
static const struct perf_event_mmap_page *
perf_evlist__pick_pc(struct evlist *evlist)
static const struct perf_event_mmap_page *evlist__pick_pc(struct evlist *evlist)
{
if (evlist) {
if (evlist->mmap && evlist->mmap[0].core.base)
......@@ -1363,9 +1362,7 @@ perf_evlist__pick_pc(struct evlist *evlist)
static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
{
const struct perf_event_mmap_page *pc;
pc = perf_evlist__pick_pc(rec->evlist);
const struct perf_event_mmap_page *pc = evlist__pick_pc(rec->evlist);
if (pc)
return pc;
return NULL;
......@@ -1444,7 +1441,7 @@ static int record__synthesize(struct record *rec, bool tail)
goto out;
}
if (!perf_evlist__exclude_kernel(rec->evlist)) {
if (!evlist__exclude_kernel(rec->evlist)) {
err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
machine);
WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
......@@ -1548,7 +1545,7 @@ static int record__setup_sb_evlist(struct record *rec)
}
}
#endif
if (perf_evlist__start_sb_thread(rec->sb_evlist, &rec->opts.target)) {
if (evlist__start_sb_thread(rec->sb_evlist, &rec->opts.target)) {
pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n");
opts->no_bpf_event = true;
}
......@@ -1689,9 +1686,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
record__init_features(rec);
if (forks) {
err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
argv, data->is_pipe,
workload_exec_failed_signal);
err = evlist__prepare_workload(rec->evlist, &opts->target, argv, data->is_pipe,
workload_exec_failed_signal);
if (err < 0) {
pr_err("Couldn't run the workload!\n");
status = err;
......@@ -1835,7 +1831,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
machine);
free(event);
perf_evlist__start_workload(rec->evlist);
evlist__start_workload(rec->evlist);
}
if (evlist__initialize_ctlfd(rec->evlist, opts->ctl_fd, opts->ctl_fd_ack))
......@@ -1861,11 +1857,11 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
* BKW_MMAP_EMPTY here: when done == true and
* hits != rec->samples in previous round.
*
* perf_evlist__toggle_bkw_mmap ensure we never
* evlist__toggle_bkw_mmap ensure we never
* convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING.
*/
if (trigger_is_hit(&switch_output_trigger) || done || draining)
perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
if (record__mmap_read_all(rec, false) < 0) {
trigger_error(&auxtrace_snapshot_trigger);
......@@ -1904,7 +1900,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
* record__mmap_read_all(): we should have collected
* data from it.
*/
perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
if (!quiet)
fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
......@@ -2066,7 +2062,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
perf_session__delete(session);
if (!opts->no_bpf_event)
perf_evlist__stop_sb_thread(rec->sb_evlist);
evlist__stop_sb_thread(rec->sb_evlist);
return status;
}
......@@ -2222,7 +2218,7 @@ static int record__parse_mmap_pages(const struct option *opt,
*p = '\0';
if (*s) {
ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
ret = __evlist__parse_mmap_pages(&mmap_pages, s);
if (ret)
goto out_free;
opts->mmap_pages = mmap_pages;
......@@ -2233,7 +2229,7 @@ static int record__parse_mmap_pages(const struct option *opt,
goto out_free;
}
ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
ret = __evlist__parse_mmap_pages(&mmap_pages, p + 1);
if (ret)
goto out_free;
......@@ -2413,7 +2409,7 @@ static bool dry_run;
* XXX Will stay a global variable till we fix builtin-script.c to stop messing
* with it and switch to use the library functions in perf_evlist that came
* from builtin-record.c, i.e. use record_opts,
* perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
* evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
* using pipes, etc.
*/
static struct option __record_options[] = {
......@@ -2476,6 +2472,8 @@ static struct option __record_options[] = {
OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
"Record the sample physical addresses"),
OPT_BOOLEAN(0, "data-page-size", &record.opts.sample_data_page_size,
"Record the sampled data address data page size"),
OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
&record.opts.sample_time_set,
......@@ -2793,7 +2791,7 @@ int cmd_record(int argc, const char **argv)
rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid;
err = -ENOMEM;
if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
if (evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
usage_with_options(record_usage, record_options);
err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
......
......@@ -211,7 +211,7 @@ static void setup_forced_leader(struct report *report,
struct evlist *evlist)
{
if (report->group_set)
perf_evlist__force_leader(evlist);
evlist__force_leader(evlist);
}
static int process_feature_event(struct perf_session *session,
......@@ -226,6 +226,8 @@ static int process_feature_event(struct perf_session *session,
pr_err("failed: wrong feature ID: %" PRI_lu64 "\n",
event->feat.feat_id);
return -1;
} else if (rep->header_only) {
session_done = 1;
}
/*
......@@ -493,8 +495,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
return ret + fprintf(fp, "\n#\n");
}
static int perf_evlist__tui_block_hists_browse(struct evlist *evlist,
struct report *rep)
static int evlist__tui_block_hists_browse(struct evlist *evlist, struct report *rep)
{
struct evsel *pos;
int i = 0, ret;
......@@ -511,9 +512,7 @@ static int perf_evlist__tui_block_hists_browse(struct evlist *evlist,
return 0;
}
static int perf_evlist__tty_browse_hists(struct evlist *evlist,
struct report *rep,
const char *help)
static int evlist__tty_browse_hists(struct evlist *evlist, struct report *rep, const char *help)
{
struct evsel *pos;
int i = 0;
......@@ -566,7 +565,7 @@ static void report__warn_kptr_restrict(const struct report *rep)
struct map *kernel_map = machine__kernel_map(&rep->session->machines.host);
struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
if (perf_evlist__exclude_kernel(rep->session->evlist))
if (evlist__exclude_kernel(rep->session->evlist))
return;
if (kernel_map == NULL ||
......@@ -595,7 +594,7 @@ static int report__gtk_browse_hists(struct report *rep, const char *help)
int (*hist_browser)(struct evlist *evlist, const char *help,
struct hist_browser_timer *timer, float min_pcnt);
hist_browser = dlsym(perf_gtk_handle, "perf_evlist__gtk_browse_hists");
hist_browser = dlsym(perf_gtk_handle, "evlist__gtk_browse_hists");
if (hist_browser == NULL) {
ui__error("GTK browser not found!\n");
......@@ -622,14 +621,12 @@ static int report__browse_hists(struct report *rep)
switch (use_browser) {
case 1:
if (rep->total_cycles_mode) {
ret = perf_evlist__tui_block_hists_browse(evlist, rep);
ret = evlist__tui_block_hists_browse(evlist, rep);
break;
}
ret = perf_evlist__tui_browse_hists(evlist, help, NULL,
rep->min_percent,
&session->header.env,
true, &rep->annotation_opts);
ret = evlist__tui_browse_hists(evlist, help, NULL, rep->min_percent,
&session->header.env, true, &rep->annotation_opts);
/*
* Usually "ret" is the last pressed key, and we only
* care if the key notifies us to switch data file.
......@@ -641,7 +638,7 @@ static int report__browse_hists(struct report *rep)
ret = report__gtk_browse_hists(rep, help);
break;
default:
ret = perf_evlist__tty_browse_hists(evlist, rep, help);
ret = evlist__tty_browse_hists(evlist, rep, help);
break;
}
......@@ -933,7 +930,7 @@ static int __cmd_report(struct report *rep)
if (dump_trace) {
perf_session__fprintf_nr_events(session, stdout);
perf_evlist__fprintf_nr_events(session->evlist, stdout);
evlist__fprintf_nr_events(session->evlist, stdout);
return 0;
}
}
......@@ -1517,6 +1514,13 @@ int cmd_report(int argc, const char **argv)
perf_session__fprintf_info(session, stdout,
report.show_full_info);
if (report.header_only) {
if (data.is_pipe) {
/*
* we need to process first few records
* which contains PERF_RECORD_HEADER_FEATURE.
*/
perf_session__process_events(session);
}
ret = 0;
goto error;
}
......
......@@ -3036,8 +3036,7 @@ static int perf_sched__timehist(struct perf_sched *sched)
setup_pager();
/* prefer sched_waking if it is captured */
if (perf_evlist__find_tracepoint_by_name(session->evlist,
"sched:sched_waking"))
if (evlist__find_tracepoint_by_name(session->evlist, "sched:sched_waking"))
handlers[1].handler = timehist_sched_wakeup_ignore;
/* setup per-evsel handlers */
......@@ -3045,8 +3044,7 @@ static int perf_sched__timehist(struct perf_sched *sched)
goto out;
/* sched_switch event at a minimum needs to exist */
if (!perf_evlist__find_tracepoint_by_name(session->evlist,
"sched:sched_switch")) {
if (!evlist__find_tracepoint_by_name(session->evlist, "sched:sched_switch")) {
pr_err("No sched_switch events found. Have you run 'perf sched record'?\n");
goto out;
}
......
......@@ -30,6 +30,7 @@
#include "util/thread-stack.h"
#include "util/time-utils.h"
#include "util/path.h"
#include "util/event.h"
#include "ui/ui.h"
#include "print_binary.h"
#include "archinsn.h"
......@@ -115,6 +116,7 @@ enum perf_output_field {
PERF_OUTPUT_SRCCODE = 1ULL << 30,
PERF_OUTPUT_IPC = 1ULL << 31,
PERF_OUTPUT_TOD = 1ULL << 32,
PERF_OUTPUT_DATA_PAGE_SIZE = 1ULL << 33,
};
struct perf_script {
......@@ -179,6 +181,7 @@ struct output_option {
{.str = "srccode", .field = PERF_OUTPUT_SRCCODE},
{.str = "ipc", .field = PERF_OUTPUT_IPC},
{.str = "tod", .field = PERF_OUTPUT_TOD},
{.str = "data_page_size", .field = PERF_OUTPUT_DATA_PAGE_SIZE},
};
enum {
......@@ -251,7 +254,8 @@ static struct {
PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD |
PERF_OUTPUT_ADDR | PERF_OUTPUT_DATA_SRC |
PERF_OUTPUT_WEIGHT | PERF_OUTPUT_PHYS_ADDR,
PERF_OUTPUT_WEIGHT | PERF_OUTPUT_PHYS_ADDR |
PERF_OUTPUT_DATA_PAGE_SIZE,
.invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
},
......@@ -499,6 +503,10 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session)
evsel__check_stype(evsel, PERF_SAMPLE_PHYS_ADDR, "PHYS_ADDR", PERF_OUTPUT_PHYS_ADDR))
return -EINVAL;
if (PRINT_FIELD(DATA_PAGE_SIZE) &&
evsel__check_stype(evsel, PERF_SAMPLE_DATA_PAGE_SIZE, "DATA_PAGE_SIZE", PERF_OUTPUT_DATA_PAGE_SIZE))
return -EINVAL;
return 0;
}
......@@ -1847,7 +1855,7 @@ static void perf_sample__fprint_metric(struct perf_script *script,
u64 val;
if (!evsel->stats)
perf_evlist__alloc_stats(script->session->evlist, false);
evlist__alloc_stats(script->session->evlist, false);
if (evsel_script(evsel->leader)->gnum++ == 0)
perf_stat__reset_shadow_stats();
val = sample->period * evsel->scale;
......@@ -1920,6 +1928,7 @@ static void process_event(struct perf_script *script,
unsigned int type = output_type(attr->type);
struct evsel_script *es = evsel->priv;
FILE *fp = es->fp;
char str[PAGE_SIZE_NAME_LEN];
if (output[type].fields == 0)
return;
......@@ -2008,6 +2017,9 @@ static void process_event(struct perf_script *script,
if (PRINT_FIELD(PHYS_ADDR))
fprintf(fp, "%16" PRIx64, sample->phys_addr);
if (PRINT_FIELD(DATA_PAGE_SIZE))
fprintf(fp, " %s", get_page_size_name(sample->data_page_size, str));
perf_sample__fprintf_ipc(sample, attr, fp);
fprintf(fp, "\n");
......@@ -2224,7 +2236,7 @@ static int print_event_with_time(struct perf_tool *tool,
{
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
struct evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
struct evsel *evsel = evlist__id2evsel(session->evlist, sample->id);
struct thread *thread = NULL;
if (evsel && !evsel->core.attr.sample_id_all) {
......@@ -3308,7 +3320,7 @@ static int set_maps(struct perf_script *script)
perf_evlist__set_maps(&evlist->core, script->cpus, script->threads);
if (perf_evlist__alloc_stats(evlist, true))
if (evlist__alloc_stats(evlist, true))
return -ENOMEM;
script->allocated = true;
......@@ -3506,7 +3518,8 @@ int cmd_script(int argc, const char **argv)
"Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
"addr,symoff,srcline,period,iregs,uregs,brstack,"
"brstacksym,flags,bpf-output,brstackinsn,brstackoff,"
"callindent,insn,insnlen,synth,phys_addr,metric,misc,ipc,tod",
"callindent,insn,insnlen,synth,phys_addr,metric,misc,ipc,tod,"
"data_page_size",
parse_output_fields),
OPT_BOOLEAN('a', "all-cpus", &system_wide,
"system-wide collection from all CPUs"),
......@@ -3935,7 +3948,7 @@ int cmd_script(int argc, const char **argv)
zfree(&script.ptime_range);
}
perf_evlist__free_stats(session->evlist);
evlist__free_stats(session->evlist);
perf_session__delete(session);
if (script_started)
......
......@@ -270,7 +270,7 @@ static void perf_stat__reset_stats(void)
{
int i;
perf_evlist__reset_stats(evsel_list);
evlist__reset_stats(evsel_list);
perf_stat__reset_shadow_stats();
for (i = 0; i < stat_config.stats_num; i++)
......@@ -534,7 +534,7 @@ static void disable_counters(void)
static volatile int workload_exec_errno;
/*
* perf_evlist__prepare_workload will send a SIGUSR1
* evlist__prepare_workload will send a SIGUSR1
* if the fork fails, since we asked by setting its
* want_signal to true.
*/
......@@ -724,8 +724,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
bool second_pass = false;
if (forks) {
if (perf_evlist__prepare_workload(evsel_list, &target, argv, is_pipe,
workload_exec_failed_signal) < 0) {
if (evlist__prepare_workload(evsel_list, &target, argv, is_pipe, workload_exec_failed_signal) < 0) {
perror("failed to prepare workload");
return -1;
}
......@@ -733,7 +732,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
}
if (group)
perf_evlist__set_leader(evsel_list);
evlist__set_leader(evsel_list);
if (affinity__setup(&affinity) < 0)
return -1;
......@@ -760,7 +759,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
if ((errno == EINVAL || errno == EBADF) &&
counter->leader != counter &&
counter->weak_group) {
perf_evlist__reset_weak_group(evsel_list, counter, false);
evlist__reset_weak_group(evsel_list, counter, false);
assert(counter->reset_group);
second_pass = true;
continue;
......@@ -843,7 +842,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
return -1;
}
if (perf_evlist__apply_filters(evsel_list, &counter)) {
if (evlist__apply_filters(evsel_list, &counter)) {
pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
counter->filter, evsel__name(counter), errno,
str_error_r(errno, msg, sizeof(msg)));
......@@ -876,7 +875,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
clock_gettime(CLOCK_MONOTONIC, &ref_time);
if (forks) {
perf_evlist__start_workload(evsel_list);
evlist__start_workload(evsel_list);
enable_counters();
if (interval || timeout || evlist__ctlfd_initialized(evsel_list))
......@@ -914,10 +913,10 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
update_stats(&walltime_nsecs_stats, t1 - t0);
if (stat_config.aggr_mode == AGGR_GLOBAL)
perf_evlist__save_aggr_prev_raw_counts(evsel_list);
evlist__save_aggr_prev_raw_counts(evsel_list);
perf_evlist__copy_prev_raw_counts(evsel_list);
perf_evlist__reset_prev_raw_counts(evsel_list);
evlist__copy_prev_raw_counts(evsel_list);
evlist__reset_prev_raw_counts(evsel_list);
runtime_stat_reset(&stat_config);
perf_stat__reset_shadow_per_stat(&rt_stat);
} else
......@@ -972,9 +971,10 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
/* Do not print anything if we record to the pipe. */
if (STAT_RECORD && perf_stat.data.is_pipe)
return;
if (stat_config.quiet)
return;
perf_evlist__print_counters(evsel_list, &stat_config, &target,
ts, argc, argv);
evlist__print_counters(evsel_list, &stat_config, &target, ts, argc, argv);
}
static volatile int signr = -1;
......@@ -1171,6 +1171,8 @@ static struct option stat_options[] = {
"threads of same physical core"),
OPT_BOOLEAN(0, "summary", &stat_config.summary,
"print summary for interval mode"),
OPT_BOOLEAN(0, "quiet", &stat_config.quiet,
"don't print output (useful with record)"),
#ifdef HAVE_LIBPFM
OPT_CALLBACK(0, "pfm-events", &evsel_list, "event",
"libpfm4 event selector. use 'perf list' to list available events",
......@@ -1904,7 +1906,7 @@ static int set_maps(struct perf_stat *st)
perf_evlist__set_maps(&evsel_list->core, st->cpus, st->threads);
if (perf_evlist__alloc_stats(evsel_list, true))
if (evlist__alloc_stats(evsel_list, true))
return -ENOMEM;
st->maps_allocated = true;
......@@ -2132,7 +2134,7 @@ int cmd_stat(int argc, const char **argv)
goto out;
}
if (!output) {
if (!output && !stat_config.quiet) {
struct timespec tm;
mode = append_file ? "a" : "w";
......@@ -2235,8 +2237,11 @@ int cmd_stat(int argc, const char **argv)
}
if (evlist__expand_cgroup(evsel_list, stat_config.cgroup_list,
&stat_config.metric_events, true) < 0)
&stat_config.metric_events, true) < 0) {
parse_options_usage(stat_usage, stat_options,
"for-each-cgroup", 0);
goto out;
}
}
target__validate(&target);
......@@ -2244,7 +2249,7 @@ int cmd_stat(int argc, const char **argv)
if ((stat_config.aggr_mode == AGGR_THREAD) && (target.system_wide))
target.per_thread = true;
if (perf_evlist__create_maps(evsel_list, &target) < 0) {
if (evlist__create_maps(evsel_list, &target) < 0) {
if (target__has_task(&target)) {
pr_err("Problems finding threads of monitor\n");
parse_options_usage(stat_usage, stat_options, "p", 1);
......@@ -2303,7 +2308,7 @@ int cmd_stat(int argc, const char **argv)
goto out;
}
if (perf_evlist__alloc_stats(evsel_list, interval))
if (evlist__alloc_stats(evsel_list, interval))
goto out;
if (perf_stat_init_aggr_mode())
......@@ -2343,7 +2348,7 @@ int cmd_stat(int argc, const char **argv)
run_idx + 1);
if (run_idx != 0)
perf_evlist__reset_prev_raw_counts(evsel_list);
evlist__reset_prev_raw_counts(evsel_list);
status = run_perf_stat(argc, argv, run_idx);
if (forever && status != -1 && !interval) {
......@@ -2394,7 +2399,7 @@ int cmd_stat(int argc, const char **argv)
}
perf_stat__exit_aggr_mode();
perf_evlist__free_stats(evsel_list);
evlist__free_stats(evsel_list);
out:
zfree(&stat_config.walltime_run);
......
......@@ -641,12 +641,9 @@ static void *display_thread_tui(void *arg)
hists->uid_filter_str = top->record_opts.target.uid_str;
}
ret = perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
top->min_percent,
&top->session->header.env,
!top->record_opts.overwrite,
&top->annotation_opts);
ret = evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent,
&top->session->header.env, !top->record_opts.overwrite,
&top->annotation_opts);
if (ret == K_RELOAD) {
top->zero = true;
goto repeat;
......@@ -782,7 +779,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
if (!machine->kptr_restrict_warned &&
symbol_conf.kptr_restrict &&
al.cpumode == PERF_RECORD_MISC_KERNEL) {
if (!perf_evlist__exclude_kernel(top->session->evlist)) {
if (!evlist__exclude_kernel(top->session->evlist)) {
ui__warning(
"Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
"Check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n"
......@@ -890,7 +887,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
while ((event = perf_mmap__read_event(&md->core)) != NULL) {
int ret;
ret = perf_evlist__parse_sample_timestamp(evlist, event, &last_timestamp);
ret = evlist__parse_sample_timestamp(evlist, event, &last_timestamp);
if (ret && ret != -1)
break;
......@@ -918,14 +915,14 @@ static void perf_top__mmap_read(struct perf_top *top)
int i;
if (overwrite)
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_DATA_PENDING);
evlist__toggle_bkw_mmap(evlist, BKW_MMAP_DATA_PENDING);
for (i = 0; i < top->evlist->core.nr_mmaps; i++)
perf_top__mmap_read_idx(top, i);
if (overwrite) {
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING);
evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING);
}
}
......@@ -1025,7 +1022,7 @@ static int perf_top__start_counters(struct perf_top *top)
goto out_err;
}
perf_evlist__config(evlist, opts, &callchain_param);
evlist__config(evlist, opts, &callchain_param);
evlist__for_each_entry(evlist, counter) {
try_again:
......@@ -1153,13 +1150,13 @@ static int deliver_event(struct ordered_events *qe,
return 0;
}
ret = perf_evlist__parse_sample(evlist, event, &sample);
ret = evlist__parse_sample(evlist, event, &sample);
if (ret) {
pr_err("Can't parse sample, err = %d\n", ret);
goto next_event;
}
evsel = perf_evlist__id2evsel(session->evlist, sample.id);
evsel = evlist__id2evsel(session->evlist, sample.id);
assert(evsel != NULL);
if (event->header.type == PERF_RECORD_SAMPLE) {
......@@ -1469,8 +1466,7 @@ int cmd_top(int argc, const char **argv)
OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
"hide kernel symbols"),
OPT_CALLBACK('m', "mmap-pages", &opts->mmap_pages, "pages",
"number of mmap data pages",
perf_evlist__parse_mmap_pages),
"number of mmap data pages", evlist__parse_mmap_pages),
OPT_INTEGER('r', "realtime", &top.realtime_prio,
"collect data with this RT SCHED_FIFO priority"),
OPT_INTEGER('d', "delay", &top.delay_secs,
......@@ -1697,7 +1693,7 @@ int cmd_top(int argc, const char **argv)
if (target__none(target))
target->system_wide = true;
if (perf_evlist__create_maps(top.evlist, target) < 0) {
if (evlist__create_maps(top.evlist, target) < 0) {
ui__error("Couldn't create thread/CPU maps: %s\n",
errno == ENOENT ? "No such process" : str_error_r(errno, errbuf, sizeof(errbuf)));
goto out_delete_evlist;
......@@ -1762,7 +1758,7 @@ int cmd_top(int argc, const char **argv)
}
#endif
if (perf_evlist__start_sb_thread(top.sb_evlist, target)) {
if (evlist__start_sb_thread(top.sb_evlist, target)) {
pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n");
opts->no_bpf_event = true;
}
......@@ -1770,7 +1766,7 @@ int cmd_top(int argc, const char **argv)
status = __cmd_top(&top);
if (!opts->no_bpf_event)
perf_evlist__stop_sb_thread(top.sb_evlist);
evlist__stop_sb_thread(top.sb_evlist);
out_delete_evlist:
evlist__delete(top.evlist);
......
......@@ -3105,7 +3105,7 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
return;
}
evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
evsel = evlist__id2evsel(trace->evlist, sample->id);
if (evsel == NULL) {
fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
return;
......@@ -3666,7 +3666,7 @@ static int trace__set_filter_loop_pids(struct trace *trace)
thread = parent;
}
err = perf_evlist__append_tp_filter_pids(trace->evlist, nr, pids);
err = evlist__append_tp_filter_pids(trace->evlist, nr, pids);
if (!err && trace->filter_pids.map)
err = bpf_map__set_filter_pids(trace->filter_pids.map, nr, pids);
......@@ -3680,11 +3680,11 @@ static int trace__set_filter_pids(struct trace *trace)
* Better not use !target__has_task() here because we need to cover the
* case where no threads were specified in the command line, but a
* workload was, and in that case we will fill in the thread_map when
* we fork the workload in perf_evlist__prepare_workload.
* we fork the workload in evlist__prepare_workload.
*/
if (trace->filter_pids.nr > 0) {
err = perf_evlist__append_tp_filter_pids(trace->evlist, trace->filter_pids.nr,
trace->filter_pids.entries);
err = evlist__append_tp_filter_pids(trace->evlist, trace->filter_pids.nr,
trace->filter_pids.entries);
if (!err && trace->filter_pids.map) {
err = bpf_map__set_filter_pids(trace->filter_pids.map, trace->filter_pids.nr,
trace->filter_pids.entries);
......@@ -3700,9 +3700,8 @@ static int __trace__deliver_event(struct trace *trace, union perf_event *event)
{
struct evlist *evlist = trace->evlist;
struct perf_sample sample;
int err;
int err = evlist__parse_sample(evlist, event, &sample);
err = perf_evlist__parse_sample(evlist, event, &sample);
if (err)
fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
else
......@@ -3735,7 +3734,7 @@ static int trace__deliver_event(struct trace *trace, union perf_event *event)
if (!trace->sort_events)
return __trace__deliver_event(trace, event);
err = perf_evlist__parse_sample_timestamp(trace->evlist, event, &trace->oe.last);
err = evlist__parse_sample_timestamp(trace->evlist, event, &trace->oe.last);
if (err && err != -1)
return err;
......@@ -3951,7 +3950,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
if (trace->cgroup)
evlist__set_default_cgroup(trace->evlist, trace->cgroup);
err = perf_evlist__create_maps(evlist, &trace->opts.target);
err = evlist__create_maps(evlist, &trace->opts.target);
if (err < 0) {
fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
goto out_delete_evlist;
......@@ -3963,14 +3962,13 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
goto out_delete_evlist;
}
perf_evlist__config(evlist, &trace->opts, &callchain_param);
evlist__config(evlist, &trace->opts, &callchain_param);
signal(SIGCHLD, sig_handler);
signal(SIGINT, sig_handler);
if (forks) {
err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
argv, false, NULL);
err = evlist__prepare_workload(evlist, &trace->opts.target, argv, false, NULL);
if (err < 0) {
fprintf(trace->output, "Couldn't run the workload!\n");
goto out_delete_evlist;
......@@ -4028,7 +4026,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
err = trace__expand_filters(trace, &evsel);
if (err)
goto out_delete_evlist;
err = perf_evlist__apply_filters(evlist, &evsel);
err = evlist__apply_filters(evlist, &evsel);
if (err < 0)
goto out_error_apply_filters;
......@@ -4043,7 +4041,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
evlist__enable(evlist);
if (forks)
perf_evlist__start_workload(evlist);
evlist__start_workload(evlist);
if (trace->opts.initial_delay) {
usleep(trace->opts.initial_delay * 1000);
......@@ -4229,12 +4227,10 @@ static int trace__replay(struct trace *trace)
if (err)
goto out;
evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
"raw_syscalls:sys_enter");
evsel = evlist__find_tracepoint_by_name(session->evlist, "raw_syscalls:sys_enter");
/* older kernels have syscalls tp versus raw_syscalls */
if (evsel == NULL)
evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
"syscalls:sys_enter");
evsel = evlist__find_tracepoint_by_name(session->evlist, "syscalls:sys_enter");
if (evsel &&
(evsel__init_raw_syscall_tp(evsel, trace__sys_enter) < 0 ||
......@@ -4243,11 +4239,9 @@ static int trace__replay(struct trace *trace)
goto out;
}
evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
"raw_syscalls:sys_exit");
evsel = evlist__find_tracepoint_by_name(session->evlist, "raw_syscalls:sys_exit");
if (evsel == NULL)
evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
"syscalls:sys_exit");
evsel = evlist__find_tracepoint_by_name(session->evlist, "syscalls:sys_exit");
if (evsel &&
(evsel__init_raw_syscall_tp(evsel, trace__sys_exit) < 0 ||
perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
......@@ -4769,8 +4763,7 @@ int cmd_trace(int argc, const char **argv)
OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
"child tasks do not inherit counters"),
OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
"number of mmap data pages",
perf_evlist__parse_mmap_pages),
"number of mmap data pages", evlist__parse_mmap_pages),
OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
"user to profile"),
OPT_CALLBACK(0, "duration", &trace, "float",
......@@ -4907,7 +4900,7 @@ int cmd_trace(int argc, const char **argv)
if (evsel) {
trace.syscalls.events.augmented = evsel;
evsel = perf_evlist__find_tracepoint_by_name(trace.evlist, "raw_syscalls:sys_enter");
evsel = evlist__find_tracepoint_by_name(trace.evlist, "raw_syscalls:sys_enter");
if (evsel == NULL) {
pr_err("ERROR: raw_syscalls:sys_enter not found in the augmented BPF object\n");
goto out;
......
......@@ -80,6 +80,7 @@ static void library_status(void)
STATUS(HAVE_LIBBPF_SUPPORT, bpf);
STATUS(HAVE_AIO_SUPPORT, aio);
STATUS(HAVE_ZSTD_SUPPORT, zstd);
STATUS(HAVE_LIBPFM, libpfm4);
}
int cmd_version(int argc, const char **argv)
......
[
{
"BriefDescription": "ddr cycles event",
"EventCode": "0x00",
"EventName": "imx8mm_ddr.cycles",
"Unit": "imx8_ddr",
"Compat": "i.MX8MM"
},
{
"BriefDescription": "ddr read-cycles event",
"EventCode": "0x2a",
"EventName": "imx8mm_ddr.read_cycles",
"Unit": "imx8_ddr",
"Compat": "i.MX8MM"
},
{
"BriefDescription": "ddr write-cycles event",
"EventCode": "0x2b",
"EventName": "imx8mm_ddr.write_cycles",
"Unit": "imx8_ddr",
"Compat": "i.MX8MM"
},
{
"BriefDescription": "ddr read event",
"EventCode": "0x35",
"EventName": "imx8mm_ddr.read",
"Unit": "imx8_ddr",
"Compat": "i.MX8MM"
},
{
"BriefDescription": "ddr write event",
"EventCode": "0x38",
"EventName": "imx8mm_ddr.write",
"Unit": "imx8_ddr",
"Compat": "i.MX8MM"
}
]
[
{
"BriefDescription": "bytes all masters read from ddr based on read-cycles event",
"MetricName": "imx8mm_ddr_read.all",
"MetricExpr": "imx8mm_ddr.read_cycles * 4 * 4",
"ScaleUnit": "9.765625e-4KB",
"Unit": "imx8_ddr",
"Compat": "i.MX8MM"
},
{
"BriefDescription": "bytes all masters write to ddr based on write-cycles event",
"MetricName": "imx8mm_ddr_write.all",
"MetricExpr": "imx8mm_ddr.write_cycles * 4 * 4",
"ScaleUnit": "9.765625e-4KB",
"Unit": "imx8_ddr",
"Compat": "i.MX8MM"
}
]
[
{
"PublicDescription": "Attributable Level 3 cache access, read",
"EventCode": "0x40",
"EventName": "L3_CACHE_RD",
"BriefDescription": "L3 cache access, read"
}
]
[
{
"ArchStdEvent": "L3_CACHE_RD"
}
]
\ No newline at end of file
[
{
"EventCode": "0xC7",
"BriefDescription": "Number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 2 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"UMask": "0x1",
"EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
"EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE",
"SampleAfterValue": "2000003",
"BriefDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired. Each count represents 1 computation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
"CounterHTOff": "0,1,2,3,4,5,6,7"
"UMask": "0x4"
},
{
"EventCode": "0xC7",
"BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT RCP FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"UMask": "0x2",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
"EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
"SampleAfterValue": "2000003",
"BriefDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired. Each count represents 1 computation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
"CounterHTOff": "0,1,2,3,4,5,6,7"
"UMask": "0x2"
},
{
"EventCode": "0xC7",
"BriefDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"UMask": "0x4",
"EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
"EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE",
"SampleAfterValue": "2000003",
"BriefDescription": "Number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired. Each count represents 2 computations. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
"CounterHTOff": "0,1,2,3,4,5,6,7"
"UMask": "0x10"
},
{
"EventCode": "0xC7",
"BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RCP DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"UMask": "0x8",
"EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
"EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE",
"SampleAfterValue": "2000003",
"BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
"CounterHTOff": "0,1,2,3,4,5,6,7"
"UMask": "0x20"
},
{
"EventCode": "0xC7",
"BriefDescription": "Cycles with any input/output SSE or FP assist",
"Counter": "0,1,2,3",
"UMask": "0x10",
"EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE",
"SampleAfterValue": "2000003",
"BriefDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired. Each count represents 4 computations. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
"CounterHTOff": "0,1,2,3,4,5,6,7"
"CounterHTOff": "0,1,2,3,4,5,6,7",
"CounterMask": "1",
"EventCode": "0xCA",
"EventName": "FP_ASSIST.ANY",
"PublicDescription": "Counts cycles with any input and output SSE or x87 FP assist. If an input and output assist are detected on the same cycle the event increments by 1.",
"SampleAfterValue": "100003",
"UMask": "0x1e"
},
{
"EventCode": "0xC7",
"BriefDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"UMask": "0x20",
"EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
"EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
"SampleAfterValue": "2000003",
"BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired. Each count represents 8 computations. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP RSQRT SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.",
"CounterHTOff": "0,1,2,3,4,5,6,7"
"UMask": "0x1"
},
{
"PublicDescription": "Counts cycles with any input and output SSE or x87 FP assist. If an input and output assist are detected on the same cycle the event increments by 1.",
"EventCode": "0xCA",
"BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RCP DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"Counter": "0,1,2,3",
"UMask": "0x1e",
"EventName": "FP_ASSIST.ANY",
"SampleAfterValue": "100003",
"BriefDescription": "Cycles with any input/output SSE or FP assist",
"CounterMask": "1",
"CounterHTOff": "0,1,2,3,4,5,6,7"
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xC7",
"EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE",
"SampleAfterValue": "2000003",
"UMask": "0x8"
}
]
\ No newline at end of file
[
{
"EventCode": "0x32",
"BriefDescription": "Number of PREFETCHW instructions executed.",
"Counter": "0,1,2,3",
"UMask": "0x1",
"EventName": "SW_PREFETCH_ACCESS.NTA",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x32",
"EventName": "SW_PREFETCH_ACCESS.PREFETCHW",
"SampleAfterValue": "2000003",
"BriefDescription": "Number of PREFETCHNTA instructions executed.",
"CounterHTOff": "0,1,2,3,4,5,6,7"
"UMask": "0x8"
},
{
"EventCode": "0x32",
"BriefDescription": "Number of PREFETCHT0 instructions executed.",
"Counter": "0,1,2,3",
"UMask": "0x2",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x32",
"EventName": "SW_PREFETCH_ACCESS.T0",
"SampleAfterValue": "2000003",
"BriefDescription": "Number of PREFETCHT0 instructions executed.",
"CounterHTOff": "0,1,2,3,4,5,6,7"
"UMask": "0x2"
},
{
"EventCode": "0x32",
"BriefDescription": "Number of hardware interrupts received by the processor.",
"Counter": "0,1,2,3",
"UMask": "0x4",
"EventName": "SW_PREFETCH_ACCESS.T1_T2",
"SampleAfterValue": "2000003",
"BriefDescription": "Number of PREFETCHT1 or PREFETCHT2 instructions executed.",
"CounterHTOff": "0,1,2,3,4,5,6,7"
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0xCB",
"EventName": "HW_INTERRUPTS.RECEIVED",
"PublicDescription": "Counts the number of hardware interruptions received by the processor.",
"SampleAfterValue": "203",
"UMask": "0x1"
},
{
"BriefDescription": "Number of PREFETCHNTA instructions executed.",
"Counter": "0,1,2,3",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x32",
"EventName": "SW_PREFETCH_ACCESS.NTA",
"SampleAfterValue": "2000003",
"UMask": "0x1"
},
{
"BriefDescription": "Number of PREFETCHT1 or PREFETCHT2 instructions executed.",
"Counter": "0,1,2,3",
"UMask": "0x8",
"EventName": "SW_PREFETCH_ACCESS.PREFETCHW",
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x32",
"EventName": "SW_PREFETCH_ACCESS.T1_T2",
"SampleAfterValue": "2000003",
"BriefDescription": "Number of PREFETCHW instructions executed.",
"CounterHTOff": "0,1,2,3,4,5,6,7"
"UMask": "0x4"
},
{
"PublicDescription": "Counts the number of hardware interruptions received by the processor.",
"EventCode": "0xCB",
"Counter": "0,1,2,3",
"UMask": "0x1",
"EventName": "HW_INTERRUPTS.RECEIVED",
"SampleAfterValue": "203",
"BriefDescription": "Number of hardware interrupts received by the processor.",
"CounterHTOff": "0,1,2,3,4,5,6,7"
"CounterHTOff": "0,1,2,3,4,5,6,7",
"EventCode": "0x09",
"EventName": "MEMORY_DISAMBIGUATION.HISTORY_RESET",
"SampleAfterValue": "2000003",
"UMask": "0x1"
}
]
\ No newline at end of file
此差异已折叠。
......@@ -12,6 +12,7 @@ enum aggr_mode_class {
*/
struct pmu_event {
const char *name;
const char *compat;
const char *event;
const char *desc;
const char *topic;
......@@ -43,10 +44,15 @@ struct pmu_events_map {
struct pmu_event *table;
};
struct pmu_sys_events {
struct pmu_event *table;
};
/*
* Global table mapping each known CPU for the architecture to its
* table of PMU events.
*/
extern struct pmu_events_map pmu_events_map[];
extern struct pmu_sys_events pmu_sys_event_tables[];
#endif
......@@ -62,6 +62,7 @@ perf-y += pfm.o
perf-y += parse-metric.o
perf-y += pe-file-parsing.o
perf-y += expand-cgroup.o
perf-y += perf-time-to-tsc.o
$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
$(call rule_mkdir)
......
......@@ -109,7 +109,7 @@ int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __m
return TEST_FAIL;
}
err = perf_evlist__create_maps(evlist, &opts.target);
err = evlist__create_maps(evlist, &opts.target);
if (err < 0) {
pr_debug("Not enough memory to create thread/cpu maps\n");
goto out_delete_evlist;
......@@ -127,7 +127,7 @@ int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __m
goto out_delete_evlist;
}
perf_evlist__config(evlist, &opts, NULL);
evlist__config(evlist, &opts, NULL);
err = evlist__open(evlist);
if (err < 0) {
......
......@@ -9,12 +9,10 @@
#include <util/util.h>
#include <util/bpf-loader.h>
#include <util/evlist.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <api/fs/fs.h>
#include <bpf/bpf.h>
#include <perf/mmap.h>
#include "tests.h"
#include "llvm.h"
......@@ -25,6 +23,8 @@
#define PERF_TEST_BPF_PATH "/sys/fs/bpf/perf_test"
#ifdef HAVE_LIBBPF_SUPPORT
#include <linux/bpf.h>
#include <bpf/bpf.h>
static int epoll_pwait_loop(void)
{
......@@ -144,23 +144,23 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
pid[sizeof(pid) - 1] = '\0';
opts.target.tid = opts.target.pid = pid;
/* Instead of perf_evlist__new_default, don't add default events */
/* Instead of evlist__new_default, don't add default events */
evlist = evlist__new();
if (!evlist) {
pr_debug("Not enough memory to create evlist\n");
return TEST_FAIL;
}
err = perf_evlist__create_maps(evlist, &opts.target);
err = evlist__create_maps(evlist, &opts.target);
if (err < 0) {
pr_debug("Not enough memory to create thread/cpu maps\n");
goto out_delete_evlist;
}
perf_evlist__splice_list_tail(evlist, &parse_state.list);
evlist__splice_list_tail(evlist, &parse_state.list);
evlist->nr_groups = parse_state.nr_groups;
perf_evlist__config(evlist, &opts, NULL);
evlist__config(evlist, &opts, NULL);
err = evlist__open(evlist);
if (err < 0) {
......
......@@ -142,6 +142,7 @@ static struct test generic_tests[] = {
.skip_if_fail = false,
.get_nr = test__wp_subtest_get_nr,
.get_desc = test__wp_subtest_get_desc,
.skip_reason = test__wp_subtest_skip_reason,
},
},
{
......@@ -349,6 +350,11 @@ static struct test generic_tests[] = {
.desc = "Event expansion for cgroups",
.func = test__expand_cgroup_events,
},
{
.desc = "Convert perf time to TSC",
.func = test__perf_time_to_tsc,
.is_supported = test__tsc_is_supported,
},
{
.func = NULL,
},
......
......@@ -378,8 +378,8 @@ static int process_sample_event(struct machine *machine,
struct thread *thread;
int ret;
if (perf_evlist__parse_sample(evlist, event, &sample)) {
pr_debug("perf_evlist__parse_sample failed\n");
if (evlist__parse_sample(evlist, event, &sample)) {
pr_debug("evlist__parse_sample failed\n");
return -1;
}
......@@ -637,7 +637,7 @@ static int do_test_code_reading(bool try_kcore)
evlist = evlist__new();
if (!evlist) {
pr_debug("perf_evlist__new failed\n");
pr_debug("evlist__new failed\n");
goto out_put;
}
......@@ -651,7 +651,7 @@ static int do_test_code_reading(bool try_kcore)
goto out_put;
}
perf_evlist__config(evlist, &opts, NULL);
evlist__config(evlist, &opts, NULL);
evsel = evlist__first(evlist);
......
......@@ -26,13 +26,13 @@ static int attach__enable_on_exec(struct evlist *evlist)
pr_debug("attaching to spawned child, enable on exec\n");
err = perf_evlist__create_maps(evlist, &target);
err = evlist__create_maps(evlist, &target);
if (err < 0) {
pr_debug("Not enough memory to create thread/cpu maps\n");
return err;
}
err = perf_evlist__prepare_workload(evlist, &target, argv, false, NULL);
err = evlist__prepare_workload(evlist, &target, argv, false, NULL);
if (err < 0) {
pr_debug("Couldn't run the workload!\n");
return err;
......@@ -47,7 +47,7 @@ static int attach__enable_on_exec(struct evlist *evlist)
return err;
}
return perf_evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL;
return evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL;
}
static int detach__enable_on_exec(struct evlist *evlist)
......
......@@ -85,11 +85,10 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unused)
{
struct evlist *evlist;
struct evsel *evsel;
struct event_name tmp;
struct evlist *evlist = evlist__new_default();
evlist = perf_evlist__new_default();
TEST_ASSERT_VAL("failed to get evlist", evlist);
evsel = evlist__first(evlist);
......
此差异已折叠。
此差异已折叠。
......@@ -92,7 +92,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un
CHECK__(parse_events(evlist, "dummy:u", NULL));
CHECK__(parse_events(evlist, "cycles:u", NULL));
perf_evlist__config(evlist, &opts, NULL);
evlist__config(evlist, &opts, NULL);
evsel = evlist__first(evlist);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册