Commit 40625491 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'perf-tools-for-v5.14-2021-07-01' of...

Merge tag 'perf-tools-for-v5.14-2021-07-01' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tool updates from Arnaldo Carvalho de Melo:
 "Tools:

   - Add cgroup support for 'perf top' (-G).

   - Add support for KVM MSRs in 'perf kvm stat'

   - Support probes on init functions in 'perf probe', to support the
     bootconfig format.

   - Improve error reporting in 'perf probe'.

   - No need to synthesize BUILD_ID records in 'perf inject' if the
     MMAP2 records have build ids already.

   - Allow toggling source code ('s' hotkey) in 'perf annotate' in all
     lines.

   - Add itrace options support to 'perf annotate'.

   - Support to custom DSO filters for 'perf script'.

  Hardware enablement:

   - Support the HYBRID_TOPOLOGY and HYBRID_CPU_PMU_CAPS features in the
     perf.data file header.

   - Support PMU prefix for mem-load and mem-store events, to support
     hybrid (BIG little) CPUs such as Intel's Alderlake.

   - Support hybrid CPUs in 'perf mem' and 'perf c2c'.

  Hardware tracing:

   - Intel PT now supports tracing KVM guests.

   - Timestamp improvements for ARM's Coresight.

  Build:

   - Add 'make -C tools/perf build-test' entries for
     libopencsd/CORESIGHT=1 and libbpf/LIBBPF_DYNAMIC=1.

   - Use bison's --file-prefix-map option to avoid storing full paths
     when using O= in the perf build.

  Tests:

   - Improve the 'perf test' entries for libpfm4 and BPF counters.

  Misc:

   - Sync msr-index.h, mount.h, kvm headers with the kernel originals.

   - Add vendor events and metrics for Intel's Icelake Server & Client"

* tag 'perf-tools-for-v5.14-2021-07-01' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux: (123 commits)
  perf session: Add missing evlist__delete when deleting a session
  perf annotate: Allow 's' on source code lines
  perf dlfilter: Add object_code() to perf_dlfilter_fns
  perf dlfilter: Add attr() to perf_dlfilter_fns
  perf dlfilter: Add srcline() to perf_dlfilter_fns
  perf dlfilter: Add insn() to perf_dlfilter_fns
  perf dlfilter: Add resolve_address() to perf_dlfilter_fns
  perf build: Install perf_dlfilter.h
  perf script: Add option to pass arguments to dlfilters
  perf script: Add option to list dlfilters
  perf script: Add dlfilter__filter_event_early()
  perf script: Add API for filtering via dynamically loaded shared object
  perf llvm: Return -ENOMEM when asprintf() fails
  perf cs-etm: Delay decode of non-timeless data until cs_etm__flush_events()
  tools headers UAPI: Synch KVM's svm.h header with the kernel
  tools kvm headers arm64: Update KVM headers from the kernel sources
  tools headers UAPI: Sync linux/kvm.h with the kernel sources
  tools headers cpufeatures: Sync with the kernel sources
  tools include UAPI: Update linux/mount.h copy
  tools arch x86: Sync the msr-index.h copy with the kernel sources
  ...
parents 71bd9341 cf96b8e4
...@@ -184,6 +184,17 @@ struct kvm_vcpu_events { ...@@ -184,6 +184,17 @@ struct kvm_vcpu_events {
__u32 reserved[12]; __u32 reserved[12];
}; };
struct kvm_arm_copy_mte_tags {
__u64 guest_ipa;
__u64 length;
void __user *addr;
__u64 flags;
__u64 reserved[2];
};
#define KVM_ARM_TAGS_TO_GUEST 0
#define KVM_ARM_TAGS_FROM_GUEST 1
/* If you need to interpret the index values, here is the key: */ /* If you need to interpret the index values, here is the key: */
#define KVM_REG_ARM_COPROC_MASK 0x000000000FFF0000 #define KVM_REG_ARM_COPROC_MASK 0x000000000FFF0000
#define KVM_REG_ARM_COPROC_SHIFT 16 #define KVM_REG_ARM_COPROC_SHIFT 16
......
...@@ -108,7 +108,7 @@ ...@@ -108,7 +108,7 @@
#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* Extended APICID (8 bits) */ #define X86_FEATURE_EXTD_APICID ( 3*32+26) /* Extended APICID (8 bits) */
#define X86_FEATURE_AMD_DCM ( 3*32+27) /* AMD multi-node processor */ #define X86_FEATURE_AMD_DCM ( 3*32+27) /* AMD multi-node processor */
#define X86_FEATURE_APERFMPERF ( 3*32+28) /* P-State hardware coordination feedback capability (APERF/MPERF MSRs) */ #define X86_FEATURE_APERFMPERF ( 3*32+28) /* P-State hardware coordination feedback capability (APERF/MPERF MSRs) */
/* free ( 3*32+29) */ #define X86_FEATURE_RAPL ( 3*32+29) /* AMD/Hygon RAPL interface */
#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */ #define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */
#define X86_FEATURE_TSC_KNOWN_FREQ ( 3*32+31) /* TSC has known frequency */ #define X86_FEATURE_TSC_KNOWN_FREQ ( 3*32+31) /* TSC has known frequency */
...@@ -378,6 +378,7 @@ ...@@ -378,6 +378,7 @@
#define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* AVX-512 Intersect for D/Q */ #define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* AVX-512 Intersect for D/Q */
#define X86_FEATURE_SRBDS_CTRL (18*32+ 9) /* "" SRBDS mitigation MSR available */ #define X86_FEATURE_SRBDS_CTRL (18*32+ 9) /* "" SRBDS mitigation MSR available */
#define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */ #define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */
#define X86_FEATURE_RTM_ALWAYS_ABORT (18*32+11) /* "" RTM transaction always aborts */
#define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */ #define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */
#define X86_FEATURE_SERIALIZE (18*32+14) /* SERIALIZE instruction */ #define X86_FEATURE_SERIALIZE (18*32+14) /* SERIALIZE instruction */
#define X86_FEATURE_HYBRID_CPU (18*32+15) /* "" This part has CPUs of more than one type */ #define X86_FEATURE_HYBRID_CPU (18*32+15) /* "" This part has CPUs of more than one type */
......
...@@ -772,6 +772,10 @@ ...@@ -772,6 +772,10 @@
#define MSR_TFA_RTM_FORCE_ABORT_BIT 0 #define MSR_TFA_RTM_FORCE_ABORT_BIT 0
#define MSR_TFA_RTM_FORCE_ABORT BIT_ULL(MSR_TFA_RTM_FORCE_ABORT_BIT) #define MSR_TFA_RTM_FORCE_ABORT BIT_ULL(MSR_TFA_RTM_FORCE_ABORT_BIT)
#define MSR_TFA_TSX_CPUID_CLEAR_BIT 1
#define MSR_TFA_TSX_CPUID_CLEAR BIT_ULL(MSR_TFA_TSX_CPUID_CLEAR_BIT)
#define MSR_TFA_SDV_ENABLE_RTM_BIT 2
#define MSR_TFA_SDV_ENABLE_RTM BIT_ULL(MSR_TFA_SDV_ENABLE_RTM_BIT)
/* P4/Xeon+ specific */ /* P4/Xeon+ specific */
#define MSR_IA32_MCG_EAX 0x00000180 #define MSR_IA32_MCG_EAX 0x00000180
......
...@@ -159,6 +159,19 @@ struct kvm_sregs { ...@@ -159,6 +159,19 @@ struct kvm_sregs {
__u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64]; __u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
}; };
struct kvm_sregs2 {
/* out (KVM_GET_SREGS2) / in (KVM_SET_SREGS2) */
struct kvm_segment cs, ds, es, fs, gs, ss;
struct kvm_segment tr, ldt;
struct kvm_dtable gdt, idt;
__u64 cr0, cr2, cr3, cr4, cr8;
__u64 efer;
__u64 apic_base;
__u64 flags;
__u64 pdptrs[4];
};
#define KVM_SREGS2_FLAGS_PDPTRS_VALID 1
/* for KVM_GET_FPU and KVM_SET_FPU */ /* for KVM_GET_FPU and KVM_SET_FPU */
struct kvm_fpu { struct kvm_fpu {
__u8 fpr[8][16]; __u8 fpr[8][16];
......
...@@ -110,6 +110,9 @@ ...@@ -110,6 +110,9 @@
#define SVM_VMGEXIT_GET_AP_JUMP_TABLE 1 #define SVM_VMGEXIT_GET_AP_JUMP_TABLE 1
#define SVM_VMGEXIT_UNSUPPORTED_EVENT 0x8000ffff #define SVM_VMGEXIT_UNSUPPORTED_EVENT 0x8000ffff
/* Exit code reserved for hypervisor/software use */
#define SVM_EXIT_SW 0xf0000000
#define SVM_EXIT_ERR -1 #define SVM_EXIT_ERR -1
#define SVM_EXIT_REASONS \ #define SVM_EXIT_REASONS \
......
...@@ -18,6 +18,8 @@ int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, ...@@ -18,6 +18,8 @@ int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
int __bitmap_equal(const unsigned long *bitmap1, int __bitmap_equal(const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int bits); const unsigned long *bitmap2, unsigned int bits);
void bitmap_clear(unsigned long *map, unsigned int start, int len); void bitmap_clear(unsigned long *map, unsigned int start, int len);
int __bitmap_intersects(const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int bits);
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
#define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1))) #define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
...@@ -170,4 +172,13 @@ static inline int bitmap_equal(const unsigned long *src1, ...@@ -170,4 +172,13 @@ static inline int bitmap_equal(const unsigned long *src1,
return __bitmap_equal(src1, src2, nbits); return __bitmap_equal(src1, src2, nbits);
} }
static inline int bitmap_intersects(const unsigned long *src1,
const unsigned long *src2, unsigned int nbits)
{
if (small_const_nbits(nbits))
return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0;
else
return __bitmap_intersects(src1, src2, nbits);
}
#endif /* _PERF_BITOPS_H */ #endif /* _PERF_BITOPS_H */
...@@ -280,6 +280,9 @@ struct kvm_xen_exit { ...@@ -280,6 +280,9 @@ struct kvm_xen_exit {
/* Encounter unexpected vm-exit reason */ /* Encounter unexpected vm-exit reason */
#define KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON 4 #define KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON 4
/* Flags that describe what fields in emulation_failure hold valid data. */
#define KVM_INTERNAL_ERROR_EMULATION_FLAG_INSTRUCTION_BYTES (1ULL << 0)
/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */ /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
struct kvm_run { struct kvm_run {
/* in */ /* in */
...@@ -383,6 +386,25 @@ struct kvm_run { ...@@ -383,6 +386,25 @@ struct kvm_run {
__u32 ndata; __u32 ndata;
__u64 data[16]; __u64 data[16];
} internal; } internal;
/*
* KVM_INTERNAL_ERROR_EMULATION
*
* "struct emulation_failure" is an overlay of "struct internal"
* that is used for the KVM_INTERNAL_ERROR_EMULATION sub-type of
* KVM_EXIT_INTERNAL_ERROR. Note, unlike other internal error
* sub-types, this struct is ABI! It also needs to be backwards
* compatible with "struct internal". Take special care that
* "ndata" is correct, that new fields are enumerated in "flags",
* and that each flag enumerates fields that are 64-bit aligned
* and sized (so that ndata+internal.data[] is valid/accurate).
*/
struct {
__u32 suberror;
__u32 ndata;
__u64 flags;
__u8 insn_size;
__u8 insn_bytes[15];
} emulation_failure;
/* KVM_EXIT_OSI */ /* KVM_EXIT_OSI */
struct { struct {
__u64 gprs[32]; __u64 gprs[32];
...@@ -1083,6 +1105,13 @@ struct kvm_ppc_resize_hpt { ...@@ -1083,6 +1105,13 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_SGX_ATTRIBUTE 196 #define KVM_CAP_SGX_ATTRIBUTE 196
#define KVM_CAP_VM_COPY_ENC_CONTEXT_FROM 197 #define KVM_CAP_VM_COPY_ENC_CONTEXT_FROM 197
#define KVM_CAP_PTP_KVM 198 #define KVM_CAP_PTP_KVM 198
#define KVM_CAP_HYPERV_ENFORCE_CPUID 199
#define KVM_CAP_SREGS2 200
#define KVM_CAP_EXIT_HYPERCALL 201
#define KVM_CAP_PPC_RPT_INVALIDATE 202
#define KVM_CAP_BINARY_STATS_FD 203
#define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204
#define KVM_CAP_ARM_MTE 205
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING
...@@ -1428,6 +1457,7 @@ struct kvm_s390_ucas_mapping { ...@@ -1428,6 +1457,7 @@ struct kvm_s390_ucas_mapping {
/* Available with KVM_CAP_PMU_EVENT_FILTER */ /* Available with KVM_CAP_PMU_EVENT_FILTER */
#define KVM_SET_PMU_EVENT_FILTER _IOW(KVMIO, 0xb2, struct kvm_pmu_event_filter) #define KVM_SET_PMU_EVENT_FILTER _IOW(KVMIO, 0xb2, struct kvm_pmu_event_filter)
#define KVM_PPC_SVM_OFF _IO(KVMIO, 0xb3) #define KVM_PPC_SVM_OFF _IO(KVMIO, 0xb3)
#define KVM_ARM_MTE_COPY_TAGS _IOR(KVMIO, 0xb4, struct kvm_arm_copy_mte_tags)
/* ioctl for vm fd */ /* ioctl for vm fd */
#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device) #define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)
...@@ -1621,6 +1651,9 @@ struct kvm_xen_hvm_attr { ...@@ -1621,6 +1651,9 @@ struct kvm_xen_hvm_attr {
#define KVM_XEN_VCPU_GET_ATTR _IOWR(KVMIO, 0xca, struct kvm_xen_vcpu_attr) #define KVM_XEN_VCPU_GET_ATTR _IOWR(KVMIO, 0xca, struct kvm_xen_vcpu_attr)
#define KVM_XEN_VCPU_SET_ATTR _IOW(KVMIO, 0xcb, struct kvm_xen_vcpu_attr) #define KVM_XEN_VCPU_SET_ATTR _IOW(KVMIO, 0xcb, struct kvm_xen_vcpu_attr)
#define KVM_GET_SREGS2 _IOR(KVMIO, 0xcc, struct kvm_sregs2)
#define KVM_SET_SREGS2 _IOW(KVMIO, 0xcd, struct kvm_sregs2)
struct kvm_xen_vcpu_attr { struct kvm_xen_vcpu_attr {
__u16 type; __u16 type;
__u16 pad[3]; __u16 pad[3];
...@@ -1899,4 +1932,76 @@ struct kvm_dirty_gfn { ...@@ -1899,4 +1932,76 @@ struct kvm_dirty_gfn {
#define KVM_BUS_LOCK_DETECTION_OFF (1 << 0) #define KVM_BUS_LOCK_DETECTION_OFF (1 << 0)
#define KVM_BUS_LOCK_DETECTION_EXIT (1 << 1) #define KVM_BUS_LOCK_DETECTION_EXIT (1 << 1)
/**
* struct kvm_stats_header - Header of per vm/vcpu binary statistics data.
* @flags: Some extra information for header, always 0 for now.
* @name_size: The size in bytes of the memory which contains statistics
* name string including trailing '\0'. The memory is allocated
* at the send of statistics descriptor.
* @num_desc: The number of statistics the vm or vcpu has.
* @id_offset: The offset of the vm/vcpu stats' id string in the file pointed
* by vm/vcpu stats fd.
* @desc_offset: The offset of the vm/vcpu stats' descriptor block in the file
* pointd by vm/vcpu stats fd.
* @data_offset: The offset of the vm/vcpu stats' data block in the file
* pointed by vm/vcpu stats fd.
*
* This is the header userspace needs to read from stats fd before any other
* readings. It is used by userspace to discover all the information about the
* vm/vcpu's binary statistics.
* Userspace reads this header from the start of the vm/vcpu's stats fd.
*/
struct kvm_stats_header {
__u32 flags;
__u32 name_size;
__u32 num_desc;
__u32 id_offset;
__u32 desc_offset;
__u32 data_offset;
};
#define KVM_STATS_TYPE_SHIFT 0
#define KVM_STATS_TYPE_MASK (0xF << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_CUMULATIVE (0x0 << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_INSTANT (0x1 << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_PEAK (0x2 << KVM_STATS_TYPE_SHIFT)
#define KVM_STATS_TYPE_MAX KVM_STATS_TYPE_PEAK
#define KVM_STATS_UNIT_SHIFT 4
#define KVM_STATS_UNIT_MASK (0xF << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_NONE (0x0 << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_BYTES (0x1 << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_SECONDS (0x2 << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_CYCLES (0x3 << KVM_STATS_UNIT_SHIFT)
#define KVM_STATS_UNIT_MAX KVM_STATS_UNIT_CYCLES
#define KVM_STATS_BASE_SHIFT 8
#define KVM_STATS_BASE_MASK (0xF << KVM_STATS_BASE_SHIFT)
#define KVM_STATS_BASE_POW10 (0x0 << KVM_STATS_BASE_SHIFT)
#define KVM_STATS_BASE_POW2 (0x1 << KVM_STATS_BASE_SHIFT)
#define KVM_STATS_BASE_MAX KVM_STATS_BASE_POW2
/**
* struct kvm_stats_desc - Descriptor of a KVM statistics.
* @flags: Annotations of the stats, like type, unit, etc.
* @exponent: Used together with @flags to determine the unit.
* @size: The number of data items for this stats.
* Every data item is of type __u64.
* @offset: The offset of the stats to the start of stat structure in
* struture kvm or kvm_vcpu.
* @unused: Unused field for future usage. Always 0 for now.
* @name: The name string for the stats. Its size is indicated by the
* &kvm_stats_header->name_size.
*/
struct kvm_stats_desc {
__u32 flags;
__s16 exponent;
__u16 size;
__u32 offset;
__u32 unused;
char name[];
};
#define KVM_GET_STATS_FD _IO(KVMIO, 0xce)
#endif /* __LINUX_KVM_H */ #endif /* __LINUX_KVM_H */
...@@ -120,6 +120,7 @@ enum fsconfig_command { ...@@ -120,6 +120,7 @@ enum fsconfig_command {
#define MOUNT_ATTR_STRICTATIME 0x00000020 /* - Always perform atime updates */ #define MOUNT_ATTR_STRICTATIME 0x00000020 /* - Always perform atime updates */
#define MOUNT_ATTR_NODIRATIME 0x00000080 /* Do not update directory access times */ #define MOUNT_ATTR_NODIRATIME 0x00000080 /* Do not update directory access times */
#define MOUNT_ATTR_IDMAP 0x00100000 /* Idmap mount to @userns_fd in struct mount_attr. */ #define MOUNT_ATTR_IDMAP 0x00100000 /* Idmap mount to @userns_fd in struct mount_attr. */
#define MOUNT_ATTR_NOSYMFOLLOW 0x00200000 /* Do not follow symlinks */
/* /*
* mount_setattr() * mount_setattr()
......
...@@ -86,3 +86,17 @@ int __bitmap_equal(const unsigned long *bitmap1, ...@@ -86,3 +86,17 @@ int __bitmap_equal(const unsigned long *bitmap1,
return 1; return 1;
} }
int __bitmap_intersects(const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int bits)
{
unsigned int k, lim = bits/BITS_PER_LONG;
for (k = 0; k < lim; ++k)
if (bitmap1[k] & bitmap2[k])
return 1;
if (bits % BITS_PER_LONG)
if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
return 1;
return 0;
}
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
L synthesize last branch entries on existing event records L synthesize last branch entries on existing event records
s skip initial number of events s skip initial number of events
q quicker (less detailed) decoding q quicker (less detailed) decoding
Z prefer to ignore timestamps (so-called "timeless" decoding)
The default is all events i.e. the same as --itrace=ibxwpe, The default is all events i.e. the same as --itrace=ibxwpe,
except for perf script where it is --itrace=ce except for perf script where it is --itrace=ce
......
...@@ -58,6 +58,13 @@ OPTIONS ...@@ -58,6 +58,13 @@ OPTIONS
--ignore-vmlinux:: --ignore-vmlinux::
Ignore vmlinux files. Ignore vmlinux files.
--itrace::
Options for decoding instruction tracing data. The options are:
include::itrace.txt[]
To disable decoding entirely, use --no-itrace.
-m:: -m::
--modules:: --modules::
Load module symbols. WARNING: use only with -k and LIVE kernel. Load module symbols. WARNING: use only with -k and LIVE kernel.
......
perf-dlfilter(1)
================
NAME
----
perf-dlfilter - Filter sample events using a dynamically loaded shared
object file
SYNOPSIS
--------
[verse]
'perf script' [--dlfilter file.so ] [ --dlarg arg ]...
DESCRIPTION
-----------
This option is used to process data through a custom filter provided by a
dynamically loaded shared object file. Arguments can be passed using --dlarg
and retrieved using perf_dlfilter_fns.args().
If 'file.so' does not contain "/", then it will be found either in the current
directory, or perf tools exec path which is ~/libexec/perf-core/dlfilters for
a local build and install (refer perf --exec-path), or the dynamic linker
paths.
API
---
The API for filtering consists of the following:
[source,c]
----
#include <perf/perf_dlfilter.h>
const struct perf_dlfilter_fns perf_dlfilter_fns;
int start(void **data, void *ctx);
int stop(void *data, void *ctx);
int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx);
int filter_event_early(void *data, const struct perf_dlfilter_sample *sample, void *ctx);
const char *filter_description(const char **long_description);
----
If implemented, 'start' will be called at the beginning, before any
calls to 'filter_event' or 'filter_event_early'. Return 0 to indicate success,
or return a negative error code. '*data' can be assigned for use by other
functions. 'ctx' is needed for calls to perf_dlfilter_fns, but most
perf_dlfilter_fns are not valid when called from 'start'.
If implemented, 'stop' will be called at the end, after any calls to
'filter_event' or 'filter_event_early'. Return 0 to indicate success, or
return a negative error code. 'data' is set by 'start'. 'ctx' is needed
for calls to perf_dlfilter_fns, but most perf_dlfilter_fns are not valid
when called from 'stop'.
If implemented, 'filter_event' will be called for each sample event.
Return 0 to keep the sample event, 1 to filter it out, or return a negative
error code. 'data' is set by 'start'. 'ctx' is needed for calls to
'perf_dlfilter_fns'.
'filter_event_early' is the same as 'filter_event' except it is called before
internal filtering.
If implemented, 'filter_description' should return a one-line description
of the filter, and optionally a longer description.
The perf_dlfilter_sample structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'filter_event' and 'filter_event_early' are passed a perf_dlfilter_sample
structure, which contains the following fields:
[source,c]
----
/*
* perf sample event information (as per perf script and <linux/perf_event.h>)
*/
struct perf_dlfilter_sample {
__u32 size; /* Size of this structure (for compatibility checking) */
__u16 ins_lat; /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
__u16 p_stage_cyc; /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
__u64 ip;
__s32 pid;
__s32 tid;
__u64 time;
__u64 addr;
__u64 id;
__u64 stream_id;
__u64 period;
__u64 weight; /* Refer PERF_SAMPLE_WEIGHT_TYPE in <linux/perf_event.h> */
__u64 transaction; /* Refer PERF_SAMPLE_TRANSACTION in <linux/perf_event.h> */
__u64 insn_cnt; /* For instructions-per-cycle (IPC) */
__u64 cyc_cnt; /* For instructions-per-cycle (IPC) */
__s32 cpu;
__u32 flags; /* Refer PERF_DLFILTER_FLAG_* above */
__u64 data_src; /* Refer PERF_SAMPLE_DATA_SRC in <linux/perf_event.h> */
__u64 phys_addr; /* Refer PERF_SAMPLE_PHYS_ADDR in <linux/perf_event.h> */
__u64 data_page_size; /* Refer PERF_SAMPLE_DATA_PAGE_SIZE in <linux/perf_event.h> */
__u64 code_page_size; /* Refer PERF_SAMPLE_CODE_PAGE_SIZE in <linux/perf_event.h> */
__u64 cgroup; /* Refer PERF_SAMPLE_CGROUP in <linux/perf_event.h> */
__u8 cpumode; /* Refer CPUMODE_MASK etc in <linux/perf_event.h> */
__u8 addr_correlates_sym; /* True => resolve_addr() can be called */
__u16 misc; /* Refer perf_event_header in <linux/perf_event.h> */
__u32 raw_size; /* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
const void *raw_data; /* Refer PERF_SAMPLE_RAW in <linux/perf_event.h> */
__u64 brstack_nr; /* Number of brstack entries */
const struct perf_branch_entry *brstack; /* Refer <linux/perf_event.h> */
__u64 raw_callchain_nr; /* Number of raw_callchain entries */
const __u64 *raw_callchain; /* Refer <linux/perf_event.h> */
const char *event;
};
----
The perf_dlfilter_fns structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The 'perf_dlfilter_fns' structure is populated with function pointers when the
file is loaded. The functions can be called by 'filter_event' or
'filter_event_early'.
[source,c]
----
struct perf_dlfilter_fns {
const struct perf_dlfilter_al *(*resolve_ip)(void *ctx);
const struct perf_dlfilter_al *(*resolve_addr)(void *ctx);
char **(*args)(void *ctx, int *dlargc);
__s32 (*resolve_address)(void *ctx, __u64 address, struct perf_dlfilter_al *al);
const __u8 *(*insn)(void *ctx, __u32 *length);
const char *(*srcline)(void *ctx, __u32 *line_number);
struct perf_event_attr *(*attr)(void *ctx);
__s32 (*object_code)(void *ctx, __u64 ip, void *buf, __u32 len);
void *(*reserved[120])(void *);
};
----
'resolve_ip' returns information about ip.
'resolve_addr' returns information about addr (if addr_correlates_sym).
'args' returns arguments from --dlarg options.
'resolve_address' provides information about 'address'. al->size must be set
before calling. Returns 0 on success, -1 otherwise.
'insn' returns instruction bytes and length.
'srcline' return source file name and line number.
'attr' returns perf_event_attr, refer <linux/perf_event.h>.
'object_code' reads object code and returns the number of bytes read.
The perf_dlfilter_al structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The 'perf_dlfilter_al' structure contains information about an address.
[source,c]
----
/*
* Address location (as per perf script)
*/
struct perf_dlfilter_al {
__u32 size; /* Size of this structure (for compatibility checking) */
__u32 symoff;
const char *sym;
__u64 addr; /* Mapped address (from dso) */
__u64 sym_start;
__u64 sym_end;
const char *dso;
__u8 sym_binding; /* STB_LOCAL, STB_GLOBAL or STB_WEAK, refer <elf.h> */
__u8 is_64_bit; /* Only valid if dso is not NULL */
__u8 is_kernel_ip; /* True if in kernel space */
__u32 buildid_size;
__u8 *buildid;
/* Below members are only populated by resolve_ip() */
__u8 filtered; /* true if this sample event will be filtered out */
const char *comm;
};
----
perf_dlfilter_sample flags
~~~~~~~~~~~~~~~~~~~~~~~~~~
The 'flags' member of 'perf_dlfilter_sample' corresponds with the flags field
of perf script. The bits of the flags are as follows:
[source,c]
----
/* Definitions for perf_dlfilter_sample flags */
enum {
PERF_DLFILTER_FLAG_BRANCH = 1ULL << 0,
PERF_DLFILTER_FLAG_CALL = 1ULL << 1,
PERF_DLFILTER_FLAG_RETURN = 1ULL << 2,
PERF_DLFILTER_FLAG_CONDITIONAL = 1ULL << 3,
PERF_DLFILTER_FLAG_SYSCALLRET = 1ULL << 4,
PERF_DLFILTER_FLAG_ASYNC = 1ULL << 5,
PERF_DLFILTER_FLAG_INTERRUPT = 1ULL << 6,
PERF_DLFILTER_FLAG_TX_ABORT = 1ULL << 7,
PERF_DLFILTER_FLAG_TRACE_BEGIN = 1ULL << 8,
PERF_DLFILTER_FLAG_TRACE_END = 1ULL << 9,
PERF_DLFILTER_FLAG_IN_TX = 1ULL << 10,
PERF_DLFILTER_FLAG_VMENTRY = 1ULL << 11,
PERF_DLFILTER_FLAG_VMEXIT = 1ULL << 12,
};
----
EXAMPLE
-------
Filter out everything except branches from "foo" to "bar":
[source,c]
----
#include <perf/perf_dlfilter.h>
#include <string.h>
const struct perf_dlfilter_fns perf_dlfilter_fns;
int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx)
{
const struct perf_dlfilter_al *al;
const struct perf_dlfilter_al *addr_al;
if (!sample->ip || !sample->addr_correlates_sym)
return 1;
al = perf_dlfilter_fns.resolve_ip(ctx);
if (!al || !al->sym || strcmp(al->sym, "foo"))
return 1;
addr_al = perf_dlfilter_fns.resolve_addr(ctx);
if (!addr_al || !addr_al->sym || strcmp(addr_al->sym, "bar"))
return 1;
return 0;
}
----
To build the shared object, assuming perf has been installed for the local user
i.e. perf_dlfilter.h is in ~/include/perf :
gcc -c -I ~/include -fpic dlfilter-example.c
gcc -shared -o dlfilter-example.so dlfilter-example.o
To use the filter with perf script:
perf script --dlfilter dlfilter-example.so
SEE ALSO
--------
linkperf:perf-script[1]
...@@ -68,6 +68,16 @@ include::itrace.txt[] ...@@ -68,6 +68,16 @@ include::itrace.txt[]
--force:: --force::
Don't complain, do it. Don't complain, do it.
--vm-time-correlation[=OPTIONS]::
Some architectures may capture AUX area data which contains timestamps
affected by virtualization. This option will update those timestamps
in place, to correlate with host timestamps. The in-place update means
that an output file is not specified, and instead the input file is
modified. The options are architecture specific, except that they may
start with "dry-run" which will cause the file to be processed but
without updating it. Currently this option is supported only by
Intel PT, refer linkperf:perf-intel-pt[1]
SEE ALSO SEE ALSO
-------- --------
linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1], linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1],
......
...@@ -174,7 +174,11 @@ Refer to script export-to-sqlite.py or export-to-postgresql.py for more details, ...@@ -174,7 +174,11 @@ Refer to script export-to-sqlite.py or export-to-postgresql.py for more details,
and to script exported-sql-viewer.py for an example of using the database. and to script exported-sql-viewer.py for an example of using the database.
There is also script intel-pt-events.py which provides an example of how to There is also script intel-pt-events.py which provides an example of how to
unpack the raw data for power events and PTWRITE. unpack the raw data for power events and PTWRITE. The script also displays
branches, and supports 2 additional modes selected by option:
--insn-trace - instruction trace
--src-trace - source trace
As mentioned above, it is easy to capture too much data. One way to limit the As mentioned above, it is easy to capture too much data. One way to limit the
data captured is to use 'snapshot' mode which is explained further below. data captured is to use 'snapshot' mode which is explained further below.
...@@ -869,6 +873,7 @@ The letters are: ...@@ -869,6 +873,7 @@ The letters are:
L synthesize last branch entries on existing event records L synthesize last branch entries on existing event records
s skip initial number of events s skip initial number of events
q quicker (less detailed) decoding q quicker (less detailed) decoding
Z prefer to ignore timestamps (so-called "timeless" decoding)
"Instructions" events look like they were recorded by "perf record -e "Instructions" events look like they were recorded by "perf record -e
instructions". instructions".
...@@ -1062,6 +1067,10 @@ What *will* be decoded with the qq option: ...@@ -1062,6 +1067,10 @@ What *will* be decoded with the qq option:
- instruction pointer associated with PSB packets - instruction pointer associated with PSB packets
The Z option is equivalent to having recorded a trace without TSC
(i.e. config term tsc=0). It can be useful to avoid timestamp issues when
decoding a trace of a virtual machine.
dump option dump option
~~~~~~~~~~~ ~~~~~~~~~~~
...@@ -1150,8 +1159,9 @@ include::build-xed.txt[] ...@@ -1150,8 +1159,9 @@ include::build-xed.txt[]
Tracing Virtual Machines Tracing Virtual Machines
------------------------ ------------------------
Currently, only kernel tracing is supported and only with "timeless" decoding Currently, only kernel tracing is supported and only with either "timeless" decoding
i.e. no TSC timestamps (i.e. no TSC timestamps) or VM Time Correlation. VM Time Correlation is an extra step
using 'perf inject' and requires unchanging VMX TSC Offset and no VMX TSC Scaling.
Other limitations and caveats Other limitations and caveats
...@@ -1162,7 +1172,7 @@ Other limitations and caveats ...@@ -1162,7 +1172,7 @@ Other limitations and caveats
Guest VCPU is unknown but may be able to be inferred from the host thread Guest VCPU is unknown but may be able to be inferred from the host thread
Callchains are not supported Callchains are not supported
Example Example using "timeless" decoding
Start VM Start VM
...@@ -1226,6 +1236,107 @@ perf script can be used to provide an instruction trace ...@@ -1226,6 +1236,107 @@ perf script can be used to provide an instruction trace
:1440 1440 ffffffffbb74603c clockevents_program_event+0x4c ([guest.kernel.kallsyms]) popq %rbx :1440 1440 ffffffffbb74603c clockevents_program_event+0x4c ([guest.kernel.kallsyms]) popq %rbx
:1440 1440 ffffffffbb74603d clockevents_program_event+0x4d ([guest.kernel.kallsyms]) popq %r12 :1440 1440 ffffffffbb74603d clockevents_program_event+0x4d ([guest.kernel.kallsyms]) popq %r12
Example using VM Time Correlation
Start VM
$ sudo virsh start kubuntu20.04
Domain kubuntu20.04 started
Mount the guest file system. Note sshfs needs -o direct_io to enable reading of proc files. root access is needed to read /proc/kcore.
$ mkdir -p vm0
$ sshfs -o direct_io root@vm0:/ vm0
Copy the guest /proc/kallsyms, /proc/modules and /proc/kcore
$ perf buildid-cache -v --kcore vm0/proc/kcore
same kcore found in /home/user/.debug/[kernel.kcore]/cc9c55a98c5e4ec0aeda69302554aabed5cd6491/2021021312450777
$ KALLSYMS=/home/user/.debug/\[kernel.kcore\]/cc9c55a98c5e4ec0aeda69302554aabed5cd6491/2021021312450777/kallsyms
Find the VM process
$ ps -eLl | grep 'KVM\|PID'
F S UID PID PPID LWP C PRI NI ADDR SZ WCHAN TTY TIME CMD
3 S 64055 16998 1 17005 13 80 0 - 1818189 - ? 00:00:16 CPU 0/KVM
3 S 64055 16998 1 17006 4 80 0 - 1818189 - ? 00:00:05 CPU 1/KVM
3 S 64055 16998 1 17007 3 80 0 - 1818189 - ? 00:00:04 CPU 2/KVM
3 S 64055 16998 1 17008 4 80 0 - 1818189 - ? 00:00:05 CPU 3/KVM
Start an open-ended perf record, tracing the VM process, do something on the VM, and then ctrl-C to stop.
IPC can be determined, hence cyc=1 can be added.
Only kernel decoding is supported, so 'k' must be specified.
Intel PT traces both the host and the guest so --guest and --host need to be specified.
$ sudo perf kvm --guest --host --guestkallsyms $KALLSYMS record --kcore -e intel_pt/cyc=1/k -p 16998
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 9.041 MB perf.data.kvm ]
Now 'perf inject' can be used to determine the VMX TCS Offset. Note, Intel PT TSC packets are
only 7-bytes, so the TSC Offset might differ from the actual value in the 8th byte. That will
have no effect i.e. the resulting timestamps will be correct anyway.
$ perf inject -i perf.data.kvm --vm-time-correlation=dry-run
ERROR: Unknown TSC Offset for VMCS 0x1bff6a
VMCS: 0x1bff6a TSC Offset 0xffffe42722c64c41
ERROR: Unknown TSC Offset for VMCS 0x1cbc08
VMCS: 0x1cbc08 TSC Offset 0xffffe42722c64c41
ERROR: Unknown TSC Offset for VMCS 0x1c3ce8
VMCS: 0x1c3ce8 TSC Offset 0xffffe42722c64c41
ERROR: Unknown TSC Offset for VMCS 0x1cbce9
VMCS: 0x1cbce9 TSC Offset 0xffffe42722c64c41
Each virtual CPU has a different Virtual Machine Control Structure (VMCS)
shown above with the calculated TSC Offset. For an unchanging TSC Offset
they should all be the same for the same virtual machine.
Now that the TSC Offset is known, it can be provided to 'perf inject'
$ perf inject -i perf.data.kvm --vm-time-correlation="dry-run 0xffffe42722c64c41"
Note the options for 'perf inject' --vm-time-correlation are:
[ dry-run ] [ <TSC Offset> [ : <VMCS> [ , <VMCS> ]... ] ]...
So it is possible to specify different TSC Offsets for different VMCS.
The option "dry-run" will cause the file to be processed but without updating it.
Note it is also possible to get a intel_pt.log file by adding option --itrace=d
There were no errors so, do it for real
$ perf inject -i perf.data.kvm --vm-time-correlation=0xffffe42722c64c41 --force
'perf script' can be used to see if there are any decoder errors
$ perf script -i perf.data.kvm --guestkallsyms $KALLSYMS --itrace=e-o
There were none.
'perf script' can be used to provide an instruction trace showing timestamps
$ perf script -i perf.data.kvm --guestkallsyms $KALLSYMS --insn-trace --xed -F+ipc | grep -C10 vmresume | head -21
CPU 1/KVM 17006 [001] 11500.262865593: ffffffff82133cdd __vmx_vcpu_run+0x3d ([kernel.kallsyms]) movq 0x48(%rax), %r9
CPU 1/KVM 17006 [001] 11500.262865593: ffffffff82133ce1 __vmx_vcpu_run+0x41 ([kernel.kallsyms]) movq 0x50(%rax), %r10
CPU 1/KVM 17006 [001] 11500.262865593: ffffffff82133ce5 __vmx_vcpu_run+0x45 ([kernel.kallsyms]) movq 0x58(%rax), %r11
CPU 1/KVM 17006 [001] 11500.262865593: ffffffff82133ce9 __vmx_vcpu_run+0x49 ([kernel.kallsyms]) movq 0x60(%rax), %r12
CPU 1/KVM 17006 [001] 11500.262865593: ffffffff82133ced __vmx_vcpu_run+0x4d ([kernel.kallsyms]) movq 0x68(%rax), %r13
CPU 1/KVM 17006 [001] 11500.262865593: ffffffff82133cf1 __vmx_vcpu_run+0x51 ([kernel.kallsyms]) movq 0x70(%rax), %r14
CPU 1/KVM 17006 [001] 11500.262865593: ffffffff82133cf5 __vmx_vcpu_run+0x55 ([kernel.kallsyms]) movq 0x78(%rax), %r15
CPU 1/KVM 17006 [001] 11500.262865593: ffffffff82133cf9 __vmx_vcpu_run+0x59 ([kernel.kallsyms]) movq (%rax), %rax
CPU 1/KVM 17006 [001] 11500.262865593: ffffffff82133cfc __vmx_vcpu_run+0x5c ([kernel.kallsyms]) callq 0xffffffff82133c40
CPU 1/KVM 17006 [001] 11500.262865593: ffffffff82133c40 vmx_vmenter+0x0 ([kernel.kallsyms]) jz 0xffffffff82133c46
CPU 1/KVM 17006 [001] 11500.262866075: ffffffff82133c42 vmx_vmenter+0x2 ([kernel.kallsyms]) vmresume IPC: 0.05 (40/769)
:17006 17006 [001] 11500.262869216: ffffffff82200cb0 asm_sysvec_apic_timer_interrupt+0x0 ([guest.kernel.kallsyms]) clac
:17006 17006 [001] 11500.262869216: ffffffff82200cb3 asm_sysvec_apic_timer_interrupt+0x3 ([guest.kernel.kallsyms]) pushq $0xffffffffffffffff
:17006 17006 [001] 11500.262869216: ffffffff82200cb5 asm_sysvec_apic_timer_interrupt+0x5 ([guest.kernel.kallsyms]) callq 0xffffffff82201160
:17006 17006 [001] 11500.262869216: ffffffff82201160 error_entry+0x0 ([guest.kernel.kallsyms]) cld
:17006 17006 [001] 11500.262869216: ffffffff82201161 error_entry+0x1 ([guest.kernel.kallsyms]) pushq %rsi
:17006 17006 [001] 11500.262869216: ffffffff82201162 error_entry+0x2 ([guest.kernel.kallsyms]) movq 0x8(%rsp), %rsi
:17006 17006 [001] 11500.262869216: ffffffff82201167 error_entry+0x7 ([guest.kernel.kallsyms]) movq %rdi, 0x8(%rsp)
:17006 17006 [001] 11500.262869216: ffffffff8220116c error_entry+0xc ([guest.kernel.kallsyms]) pushq %rdx
:17006 17006 [001] 11500.262869216: ffffffff8220116d error_entry+0xd ([guest.kernel.kallsyms]) pushq %rcx
:17006 17006 [001] 11500.262869216: ffffffff8220116e error_entry+0xe ([guest.kernel.kallsyms]) pushq %rax
SEE ALSO SEE ALSO
......
...@@ -226,7 +226,7 @@ So, "source.c:100-120" shows lines between 100th to l20th in source.c file. And ...@@ -226,7 +226,7 @@ So, "source.c:100-120" shows lines between 100th to l20th in source.c file. And
LAZY MATCHING LAZY MATCHING
------------- -------------
The lazy line matching is similar to glob matching but ignoring spaces in both of pattern and target. So this accepts wildcards('*', '?') and character classes(e.g. [a-z], [!A-Z]). The lazy line matching is similar to glob matching but ignoring spaces in both of pattern and target. So this accepts wildcards('*', '?') and character classes(e.g. [a-z], [!A-Z]).
e.g. e.g.
'a=*' can matches 'a=b', 'a = b', 'a == b' and so on. 'a=*' can matches 'a=b', 'a = b', 'a == b' and so on.
...@@ -235,8 +235,8 @@ This provides some sort of flexibility and robustness to probe point definitions ...@@ -235,8 +235,8 @@ This provides some sort of flexibility and robustness to probe point definitions
FILTER PATTERN FILTER PATTERN
-------------- --------------
The filter pattern is a glob matching pattern(s) to filter variables. The filter pattern is a glob matching pattern(s) to filter variables.
In addition, you can use "!" for specifying filter-out rule. You also can give several rules combined with "&" or "|", and fold those rules as one rule by using "(" ")". In addition, you can use "!" for specifying filter-out rule. You also can give several rules combined with "&" or "|", and fold those rules as one rule by using "(" ")".
e.g. e.g.
With --filter "foo* | bar*", perf probe -V shows variables which start with "foo" or "bar". With --filter "foo* | bar*", perf probe -V shows variables which start with "foo" or "bar".
...@@ -295,6 +295,19 @@ Add a probe in a source file using special characters by backslash escape ...@@ -295,6 +295,19 @@ Add a probe in a source file using special characters by backslash escape
./perf probe -x /opt/test/a.out 'foo\+bar.c:4' ./perf probe -x /opt/test/a.out 'foo\+bar.c:4'
PERMISSIONS AND SYSCTL
----------------------
Since perf probe depends on ftrace (tracefs) and kallsyms (/proc/kallsyms), you have to care about the permission and some sysctl knobs.
- Since tracefs and kallsyms requires root or privileged user to access it, the following perf probe commands also require it; --add, --del, --list (except for --cache option)
- The system admin can remount the tracefs with 755 (`sudo mount -o remount,mode=755 /sys/kernel/tracing/`) to allow unprivileged user to run the perf probe --list command.
- /proc/sys/kernel/kptr_restrict = 2 (restrict all users) also prevents perf probe to retrieve the important information from kallsyms. You also need to set to 1 (restrict non CAP_SYSLOG users) for the above commands. Since the user-space probe doesn't need to access kallsyms, this is only for probing the kernel function (kprobes).
- Since the perf probe commands read the vmlinux (for kernel) and/or the debuginfo file (including user-space application), you need to ensure that you can read those files.
SEE ALSO SEE ALSO
-------- --------
linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1] linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1]
...@@ -550,6 +550,27 @@ def trace_unhandled(event_name, context, event_fields_dict): ...@@ -550,6 +550,27 @@ def trace_unhandled(event_name, context, event_fields_dict):
pass pass
---- ----
*process_event*, if defined, is called for any non-tracepoint event
----
def process_event(param_dict):
pass
----
*context_switch*, if defined, is called for any context switch
----
def context_switch(ts, cpu, pid, tid, np_pid, np_tid, machine_pid, out, out_preempt, *x):
pass
----
*auxtrace_error*, if defined, is called for any AUX area tracing error
----
def auxtrace_error(typ, code, cpu, pid, tid, ip, ts, msg, cpumode, *x):
pass
----
The remaining sections provide descriptions of each of the available The remaining sections provide descriptions of each of the available
built-in perf script Python modules and their associated functions. built-in perf script Python modules and their associated functions.
...@@ -592,12 +613,18 @@ common, but need to be made accessible to user scripts nonetheless. ...@@ -592,12 +613,18 @@ common, but need to be made accessible to user scripts nonetheless.
perf_trace_context defines a set of functions that can be used to perf_trace_context defines a set of functions that can be used to
access this data in the context of the current event. Each of these access this data in the context of the current event. Each of these
functions expects a context variable, which is the same as the functions expects a context variable, which is the same as the
context variable passed into every event handler as the second context variable passed into every tracepoint event handler as the second
argument. argument. For non-tracepoint events, the context variable is also present
as perf_trace_context.perf_script_context .
common_pc(context) - returns common_preempt count for the current event common_pc(context) - returns common_preempt count for the current event
common_flags(context) - returns common_flags for the current event common_flags(context) - returns common_flags for the current event
common_lock_depth(context) - returns common_lock_depth for the current event common_lock_depth(context) - returns common_lock_depth for the current event
perf_sample_insn(context) - returns the machine code instruction
perf_set_itrace_options(context, itrace_options) - set --itrace options if they have not been set already
perf_sample_srcline(context) - returns source_file_name, line_number
perf_sample_srccode(context) - returns source_file_name, line_number, source_line
Util.py Module Util.py Module
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
...@@ -616,9 +643,20 @@ SUPPORTED FIELDS ...@@ -616,9 +643,20 @@ SUPPORTED FIELDS
Currently supported fields: Currently supported fields:
ev_name, comm, pid, tid, cpu, ip, time, period, phys_addr, addr, ev_name, comm, pid, tid, cpu, ip, time, period, phys_addr, addr,
symbol, dso, time_enabled, time_running, values, callchain, symbol, symoff, dso, time_enabled, time_running, values, callchain,
brstack, brstacksym, datasrc, datasrc_decode, iregs, uregs, brstack, brstacksym, datasrc, datasrc_decode, iregs, uregs,
weight, transaction, raw_buf, attr. weight, transaction, raw_buf, attr, cpumode.
Fields that may also be present:
flags - sample flags
flags_disp - sample flags display
insn_cnt - instruction count for determining instructions-per-cycle (IPC)
cyc_cnt - cycle count for determining IPC
addr_correlates_sym - addr can correlate to a symbol
addr_dso - addr dso
addr_symbol - addr symbol
addr_symoff - addr symbol offset
Some fields have sub items: Some fields have sub items:
......
...@@ -98,6 +98,18 @@ OPTIONS ...@@ -98,6 +98,18 @@ OPTIONS
Generate perf-script.[ext] starter script for given language, Generate perf-script.[ext] starter script for given language,
using current perf.data. using current perf.data.
--dlfilter=<file>::
Filter sample events using the given shared object file.
Refer linkperf:perf-dlfilter[1]
--dlarg=<arg>::
Pass 'arg' as an argument to the dlfilter. --dlarg may be repeated
to add more arguments.
--list-dlfilters=::
Display a list of available dlfilters. Use with option -v (must come
before option --list-dlfilters) to show long descriptions.
-a:: -a::
Force system-wide collection. Scripts run without a <command> Force system-wide collection. Scripts run without a <command>
normally use -a by default, while scripts run with a <command> normally use -a by default, while scripts run with a <command>
...@@ -483,4 +495,5 @@ include::itrace.txt[] ...@@ -483,4 +495,5 @@ include::itrace.txt[]
SEE ALSO SEE ALSO
-------- --------
linkperf:perf-record[1], linkperf:perf-script-perl[1], linkperf:perf-record[1], linkperf:perf-script-perl[1],
linkperf:perf-script-python[1], linkperf:perf-intel-pt[1] linkperf:perf-script-python[1], linkperf:perf-intel-pt[1],
linkperf:perf-dlfilter[1]
...@@ -277,6 +277,18 @@ Default is to monitor all CPUS. ...@@ -277,6 +277,18 @@ Default is to monitor all CPUS.
Record events of type PERF_RECORD_NAMESPACES and display it with the Record events of type PERF_RECORD_NAMESPACES and display it with the
'cgroup_id' sort key. 'cgroup_id' sort key.
-G name::
--cgroup name::
monitor only in the container (cgroup) called "name". This option is available only
in per-cpu mode. The cgroup filesystem must be mounted. All threads belonging to
container "name" are monitored when they run on the monitored CPUs. Multiple cgroups
can be provided. Each cgroup is applied to the corresponding event, i.e., first cgroup
to first event, second cgroup to second event and so on. It is possible to provide
an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have
corresponding events, i.e., they always refer to events defined earlier on the command
line. If the user wants to track multiple events for a specific cgroup, the user can
use '-e e1 -e e2 -G foo,foo' or just use '-e e1 -e e2 -G foo'.
--all-cgroups:: --all-cgroups::
Record events of type PERF_RECORD_CGROUP and display it with the Record events of type PERF_RECORD_CGROUP and display it with the
'cgroup' sort key. 'cgroup' sort key.
......
...@@ -402,6 +402,39 @@ struct { ...@@ -402,6 +402,39 @@ struct {
u64 clockid_time_ns; u64 clockid_time_ns;
}; };
HEADER_HYBRID_TOPOLOGY = 30,
Indicate the hybrid CPUs. The format of data is as below.
struct {
u32 nr;
struct {
char pmu_name[];
char cpus[];
} [nr]; /* Variable length records */
};
Example:
hybrid cpu system:
cpu_core cpu list : 0-15
cpu_atom cpu list : 16-23
HEADER_HYBRID_CPU_PMU_CAPS = 31,
A list of hybrid CPU PMU capabilities.
struct {
u32 nr_pmu;
struct {
u32 nr_cpu_pmu_caps;
{
char name[];
char value[];
} [nr_cpu_pmu_caps];
char pmu_name[];
} [nr_pmu];
};
other bits are reserved and should ignored for now other bits are reserved and should ignored for now
HEADER_FEAT_BITS = 256, HEADER_FEAT_BITS = 256,
......
...@@ -201,6 +201,12 @@ ifeq ($(call get-executable,$(BISON)),) ...@@ -201,6 +201,12 @@ ifeq ($(call get-executable,$(BISON)),)
dummy := $(error Error: $(BISON) is missing on this system, please install it) dummy := $(error Error: $(BISON) is missing on this system, please install it)
endif endif
ifneq ($(OUTPUT),)
ifeq ($(shell expr $(shell $(BISON) --version | grep bison | sed -e 's/.\+ \([0-9]\+\).\([0-9]\+\).\([0-9]\+\)/\1\2\3/g') \>\= 371), 1)
BISON_FILE_PREFIX_MAP := --file-prefix-map=$(OUTPUT)=
endif
endif
# Treat warnings as errors unless directed not to # Treat warnings as errors unless directed not to
ifneq ($(WERROR),0) ifneq ($(WERROR),0)
CORE_CFLAGS += -Werror CORE_CFLAGS += -Werror
...@@ -634,7 +640,7 @@ endif ...@@ -634,7 +640,7 @@ endif
ifdef BUILD_BPF_SKEL ifdef BUILD_BPF_SKEL
$(call feature_check,clang-bpf-co-re) $(call feature_check,clang-bpf-co-re)
ifeq ($(feature-clang-bpf-co-re), 0) ifeq ($(feature-clang-bpf-co-re), 0)
dummy := $(error Error: clang too old. Please install recent clang) dummy := $(error Error: clang too old/not installed. Please install recent clang to build with BUILD_BPF_SKEL)
endif endif
$(call detected,CONFIG_PERF_BPF_SKEL) $(call detected,CONFIG_PERF_BPF_SKEL)
CFLAGS += -DHAVE_BPF_SKEL CFLAGS += -DHAVE_BPF_SKEL
...@@ -1111,6 +1117,8 @@ prefix ?= $(HOME) ...@@ -1111,6 +1117,8 @@ prefix ?= $(HOME)
endif endif
bindir_relative = bin bindir_relative = bin
bindir = $(abspath $(prefix)/$(bindir_relative)) bindir = $(abspath $(prefix)/$(bindir_relative))
includedir_relative = include
includedir = $(abspath $(prefix)/$(includedir_relative))
mandir = share/man mandir = share/man
infodir = share/info infodir = share/info
perfexecdir = libexec/perf-core perfexecdir = libexec/perf-core
...@@ -1143,6 +1151,7 @@ ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG)) ...@@ -1143,6 +1151,7 @@ ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG))
STRACE_GROUPS_DIR_SQ = $(subst ','\'',$(STRACE_GROUPS_DIR)) STRACE_GROUPS_DIR_SQ = $(subst ','\'',$(STRACE_GROUPS_DIR))
DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
bindir_SQ = $(subst ','\'',$(bindir)) bindir_SQ = $(subst ','\'',$(bindir))
includedir_SQ = $(subst ','\'',$(includedir))
mandir_SQ = $(subst ','\'',$(mandir)) mandir_SQ = $(subst ','\'',$(mandir))
infodir_SQ = $(subst ','\'',$(infodir)) infodir_SQ = $(subst ','\'',$(infodir))
perfexecdir_SQ = $(subst ','\'',$(perfexecdir)) perfexecdir_SQ = $(subst ','\'',$(perfexecdir))
...@@ -1227,6 +1236,9 @@ $(call detected_var,LIBDIR) ...@@ -1227,6 +1236,9 @@ $(call detected_var,LIBDIR)
$(call detected_var,GTK_CFLAGS) $(call detected_var,GTK_CFLAGS)
$(call detected_var,PERL_EMBED_CCOPTS) $(call detected_var,PERL_EMBED_CCOPTS)
$(call detected_var,PYTHON_EMBED_CCOPTS) $(call detected_var,PYTHON_EMBED_CCOPTS)
ifneq ($(BISON_FILE_PREFIX_MAP),)
$(call detected_var,BISON_FILE_PREFIX_MAP)
endif
# re-generate FEATURE-DUMP as we may have called feature_check, found out # re-generate FEATURE-DUMP as we may have called feature_check, found out
# extra libraries to add to LDFLAGS of some other test and then redo those # extra libraries to add to LDFLAGS of some other test and then redo those
......
...@@ -923,7 +923,9 @@ install-tools: all install-gtk ...@@ -923,7 +923,9 @@ install-tools: all install-gtk
$(call QUIET_INSTALL, binaries) \ $(call QUIET_INSTALL, binaries) \
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \
$(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \ $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \
$(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace' $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(dir_SQ)/trace'; \
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(includedir_SQ)/perf'; \
$(INSTALL) util/perf_dlfilter.h -t '$(DESTDIR_SQ)$(includedir_SQ)/perf'
ifndef NO_PERF_READ_VDSO32 ifndef NO_PERF_READ_VDSO32
$(call QUIET_INSTALL, perf-read-vdso32) \ $(call QUIET_INSTALL, perf-read-vdso32) \
$(INSTALL) $(OUTPUT)perf-read-vdso32 '$(DESTDIR_SQ)$(bindir_SQ)'; $(INSTALL) $(OUTPUT)perf-read-vdso32 '$(DESTDIR_SQ)$(bindir_SQ)';
......
...@@ -2,11 +2,6 @@ ...@@ -2,11 +2,6 @@
#ifndef ARCH_TESTS_H #ifndef ARCH_TESTS_H
#define ARCH_TESTS_H #define ARCH_TESTS_H
#ifdef HAVE_DWARF_UNWIND_SUPPORT
struct thread;
struct perf_sample;
#endif
extern struct test arch_tests[]; extern struct test arch_tests[];
#endif #endif
...@@ -38,8 +38,6 @@ struct cs_etm_recording { ...@@ -38,8 +38,6 @@ struct cs_etm_recording {
struct auxtrace_record itr; struct auxtrace_record itr;
struct perf_pmu *cs_etm_pmu; struct perf_pmu *cs_etm_pmu;
struct evlist *evlist; struct evlist *evlist;
int wrapped_cnt;
bool *wrapped;
bool snapshot_mode; bool snapshot_mode;
size_t snapshot_size; size_t snapshot_size;
}; };
...@@ -734,135 +732,6 @@ static int cs_etm_info_fill(struct auxtrace_record *itr, ...@@ -734,135 +732,6 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
return 0; return 0;
} }
static int cs_etm_alloc_wrapped_array(struct cs_etm_recording *ptr, int idx)
{
bool *wrapped;
int cnt = ptr->wrapped_cnt;
/* Make @ptr->wrapped as big as @idx */
while (cnt <= idx)
cnt++;
/*
* Free'ed in cs_etm_recording_free(). Using realloc() to avoid
* cross compilation problems where the host's system supports
* reallocarray() but not the target.
*/
wrapped = realloc(ptr->wrapped, cnt * sizeof(bool));
if (!wrapped)
return -ENOMEM;
wrapped[cnt - 1] = false;
ptr->wrapped_cnt = cnt;
ptr->wrapped = wrapped;
return 0;
}
static bool cs_etm_buffer_has_wrapped(unsigned char *buffer,
size_t buffer_size, u64 head)
{
u64 i, watermark;
u64 *buf = (u64 *)buffer;
size_t buf_size = buffer_size;
/*
* We want to look the very last 512 byte (chosen arbitrarily) in
* the ring buffer.
*/
watermark = buf_size - 512;
/*
* @head is continuously increasing - if its value is equal or greater
* than the size of the ring buffer, it has wrapped around.
*/
if (head >= buffer_size)
return true;
/*
* The value of @head is somewhere within the size of the ring buffer.
* This can be that there hasn't been enough data to fill the ring
* buffer yet or the trace time was so long that @head has numerically
* wrapped around. To find we need to check if we have data at the very
* end of the ring buffer. We can reliably do this because mmap'ed
* pages are zeroed out and there is a fresh mapping with every new
* session.
*/
/* @head is less than 512 byte from the end of the ring buffer */
if (head > watermark)
watermark = head;
/*
* Speed things up by using 64 bit transactions (see "u64 *buf" above)
*/
watermark >>= 3;
buf_size >>= 3;
/*
* If we find trace data at the end of the ring buffer, @head has
* been there and has numerically wrapped around at least once.
*/
for (i = watermark; i < buf_size; i++)
if (buf[i])
return true;
return false;
}
static int cs_etm_find_snapshot(struct auxtrace_record *itr,
int idx, struct auxtrace_mmap *mm,
unsigned char *data,
u64 *head, u64 *old)
{
int err;
bool wrapped;
struct cs_etm_recording *ptr =
container_of(itr, struct cs_etm_recording, itr);
/*
* Allocate memory to keep track of wrapping if this is the first
* time we deal with this *mm.
*/
if (idx >= ptr->wrapped_cnt) {
err = cs_etm_alloc_wrapped_array(ptr, idx);
if (err)
return err;
}
/*
* Check to see if *head has wrapped around. If it hasn't only the
* amount of data between *head and *old is snapshot'ed to avoid
* bloating the perf.data file with zeros. But as soon as *head has
* wrapped around the entire size of the AUX ring buffer it taken.
*/
wrapped = ptr->wrapped[idx];
if (!wrapped && cs_etm_buffer_has_wrapped(data, mm->len, *head)) {
wrapped = true;
ptr->wrapped[idx] = true;
}
pr_debug3("%s: mmap index %d old head %zu new head %zu size %zu\n",
__func__, idx, (size_t)*old, (size_t)*head, mm->len);
/* No wrap has occurred, we can just use *head and *old. */
if (!wrapped)
return 0;
/*
* *head has wrapped around - adjust *head and *old to pickup the
* entire content of the AUX buffer.
*/
if (*head >= mm->len) {
*old = *head - mm->len;
} else {
*head += mm->len;
*old = *head - mm->len;
}
return 0;
}
static int cs_etm_snapshot_start(struct auxtrace_record *itr) static int cs_etm_snapshot_start(struct auxtrace_record *itr)
{ {
struct cs_etm_recording *ptr = struct cs_etm_recording *ptr =
...@@ -900,7 +769,6 @@ static void cs_etm_recording_free(struct auxtrace_record *itr) ...@@ -900,7 +769,6 @@ static void cs_etm_recording_free(struct auxtrace_record *itr)
struct cs_etm_recording *ptr = struct cs_etm_recording *ptr =
container_of(itr, struct cs_etm_recording, itr); container_of(itr, struct cs_etm_recording, itr);
zfree(&ptr->wrapped);
free(ptr); free(ptr);
} }
...@@ -928,7 +796,6 @@ struct auxtrace_record *cs_etm_record_init(int *err) ...@@ -928,7 +796,6 @@ struct auxtrace_record *cs_etm_record_init(int *err)
ptr->itr.recording_options = cs_etm_recording_options; ptr->itr.recording_options = cs_etm_recording_options;
ptr->itr.info_priv_size = cs_etm_info_priv_size; ptr->itr.info_priv_size = cs_etm_info_priv_size;
ptr->itr.info_fill = cs_etm_info_fill; ptr->itr.info_fill = cs_etm_info_fill;
ptr->itr.find_snapshot = cs_etm_find_snapshot;
ptr->itr.snapshot_start = cs_etm_snapshot_start; ptr->itr.snapshot_start = cs_etm_snapshot_start;
ptr->itr.snapshot_finish = cs_etm_snapshot_finish; ptr->itr.snapshot_finish = cs_etm_snapshot_finish;
ptr->itr.reference = cs_etm_reference; ptr->itr.reference = cs_etm_reference;
......
...@@ -2,11 +2,6 @@ ...@@ -2,11 +2,6 @@
#ifndef ARCH_TESTS_H #ifndef ARCH_TESTS_H
#define ARCH_TESTS_H #define ARCH_TESTS_H
#ifdef HAVE_DWARF_UNWIND_SUPPORT
struct thread;
struct perf_sample;
#endif
extern struct test arch_tests[]; extern struct test arch_tests[];
#endif #endif
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "../../../util/cpumap.h" #include "../../../util/cpumap.h"
#include "../../../util/event.h" #include "../../../util/event.h"
#include "../../../util/evsel.h" #include "../../../util/evsel.h"
#include "../../../util/evsel_config.h"
#include "../../../util/evlist.h" #include "../../../util/evlist.h"
#include "../../../util/session.h" #include "../../../util/session.h"
#include <internal/lib.h> // page_size #include <internal/lib.h> // page_size
...@@ -32,6 +33,29 @@ struct arm_spe_recording { ...@@ -32,6 +33,29 @@ struct arm_spe_recording {
struct evlist *evlist; struct evlist *evlist;
}; };
static void arm_spe_set_timestamp(struct auxtrace_record *itr,
struct evsel *evsel)
{
struct arm_spe_recording *ptr;
struct perf_pmu *arm_spe_pmu;
struct evsel_config_term *term = evsel__get_config_term(evsel, CFG_CHG);
u64 user_bits = 0, bit;
ptr = container_of(itr, struct arm_spe_recording, itr);
arm_spe_pmu = ptr->arm_spe_pmu;
if (term)
user_bits = term->val.cfg_chg;
bit = perf_pmu__format_bits(&arm_spe_pmu->format, "ts_enable");
/* Skip if user has set it */
if (bit & user_bits)
return;
evsel->core.attr.config |= bit;
}
static size_t static size_t
arm_spe_info_priv_size(struct auxtrace_record *itr __maybe_unused, arm_spe_info_priv_size(struct auxtrace_record *itr __maybe_unused,
struct evlist *evlist __maybe_unused) struct evlist *evlist __maybe_unused)
...@@ -68,6 +92,7 @@ static int arm_spe_recording_options(struct auxtrace_record *itr, ...@@ -68,6 +92,7 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
container_of(itr, struct arm_spe_recording, itr); container_of(itr, struct arm_spe_recording, itr);
struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu; struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu;
struct evsel *evsel, *arm_spe_evsel = NULL; struct evsel *evsel, *arm_spe_evsel = NULL;
struct perf_cpu_map *cpus = evlist->core.cpus;
bool privileged = perf_event_paranoid_check(-1); bool privileged = perf_event_paranoid_check(-1);
struct evsel *tracking_evsel; struct evsel *tracking_evsel;
int err; int err;
...@@ -91,7 +116,7 @@ static int arm_spe_recording_options(struct auxtrace_record *itr, ...@@ -91,7 +116,7 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
return 0; return 0;
/* We are in full trace mode but '-m,xyz' wasn't specified */ /* We are in full trace mode but '-m,xyz' wasn't specified */
if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) { if (!opts->auxtrace_mmap_pages) {
if (privileged) { if (privileged) {
opts->auxtrace_mmap_pages = MiB(4) / page_size; opts->auxtrace_mmap_pages = MiB(4) / page_size;
} else { } else {
...@@ -120,9 +145,14 @@ static int arm_spe_recording_options(struct auxtrace_record *itr, ...@@ -120,9 +145,14 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
*/ */
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); * In the case of per-cpu mmaps, sample CPU for AUX event;
evsel__set_sample_bit(arm_spe_evsel, TID); * also enable the timestamp tracing for samples correlation.
*/
if (!perf_cpu_map__empty(cpus)) {
evsel__set_sample_bit(arm_spe_evsel, CPU);
arm_spe_set_timestamp(itr, arm_spe_evsel);
}
/* Add dummy event to keep tracking */ /* Add dummy event to keep tracking */
err = parse_events(evlist, "dummy:u", NULL); err = parse_events(evlist, "dummy:u", NULL);
...@@ -134,9 +164,10 @@ static int arm_spe_recording_options(struct auxtrace_record *itr, ...@@ -134,9 +164,10 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
tracking_evsel->core.attr.freq = 0; tracking_evsel->core.attr.freq = 0;
tracking_evsel->core.attr.sample_period = 1; tracking_evsel->core.attr.sample_period = 1;
evsel__set_sample_bit(tracking_evsel, TIME);
evsel__set_sample_bit(tracking_evsel, CPU); /* In per-cpu case, always need the time of mmap events etc */
evsel__reset_sample_bit(tracking_evsel, BRANCH_STACK); if (!perf_cpu_map__empty(cpus))
evsel__set_sample_bit(tracking_evsel, TIME);
return 0; return 0;
} }
......
...@@ -20,7 +20,7 @@ struct perf_mem_event *perf_mem_events__ptr(int i) ...@@ -20,7 +20,7 @@ struct perf_mem_event *perf_mem_events__ptr(int i)
return &perf_mem_events[i]; return &perf_mem_events[i];
} }
char *perf_mem_events__name(int i) char *perf_mem_events__name(int i, char *pmu_name __maybe_unused)
{ {
struct perf_mem_event *e = perf_mem_events__ptr(i); struct perf_mem_event *e = perf_mem_events__ptr(i);
......
...@@ -2,13 +2,6 @@ ...@@ -2,13 +2,6 @@
#ifndef ARCH_TESTS_H #ifndef ARCH_TESTS_H
#define ARCH_TESTS_H #define ARCH_TESTS_H
#ifdef HAVE_DWARF_UNWIND_SUPPORT
struct thread;
struct perf_sample;
int test__arch_unwind_sample(struct perf_sample *sample,
struct thread *thread);
#endif
extern struct test arch_tests[]; extern struct test arch_tests[];
#endif #endif
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include "event.h" #include "event.h"
#include "debug.h" #include "debug.h"
#include "tests/tests.h" #include "tests/tests.h"
#include "arch-tests.h"
#define STACK_SIZE 8192 #define STACK_SIZE 8192
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#include "mem-events.h" #include "mem-events.h"
/* PowerPC does not support 'ldlat' parameter. */ /* PowerPC does not support 'ldlat' parameter. */
char *perf_mem_events__name(int i) char *perf_mem_events__name(int i, char *pmu_name __maybe_unused)
{ {
if (i == PERF_MEM_EVENTS__LOAD) if (i == PERF_MEM_EVENTS__LOAD)
return (char *) "cpu/mem-loads/"; return (char *) "cpu/mem-loads/";
......
...@@ -2,23 +2,15 @@ ...@@ -2,23 +2,15 @@
#ifndef ARCH_TESTS_H #ifndef ARCH_TESTS_H
#define ARCH_TESTS_H #define ARCH_TESTS_H
#include <linux/compiler.h>
struct test; struct test;
/* Tests */ /* Tests */
int test__rdpmc(struct test *test __maybe_unused, int subtest); int test__rdpmc(struct test *test, int subtest);
int test__insn_x86(struct test *test __maybe_unused, int subtest); int test__insn_x86(struct test *test, int subtest);
int test__intel_pt_pkt_decoder(struct test *test, int subtest); int test__intel_pt_pkt_decoder(struct test *test, int subtest);
int test__bp_modify(struct test *test, int subtest); int test__bp_modify(struct test *test, int subtest);
int test__x86_sample_parsing(struct test *test, int subtest); int test__x86_sample_parsing(struct test *test, int subtest);
#ifdef HAVE_DWARF_UNWIND_SUPPORT
struct thread;
struct perf_sample;
int test__arch_unwind_sample(struct perf_sample *sample,
struct thread *thread);
#endif
extern struct test arch_tests[]; extern struct test arch_tests[];
#endif #endif
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include "event.h" #include "event.h"
#include "debug.h" #include "debug.h"
#include "tests/tests.h" #include "tests/tests.h"
#include "arch-tests.h"
#define STACK_SIZE 8192 #define STACK_SIZE 8192
......
...@@ -133,11 +133,56 @@ static struct kvm_events_ops ioport_events = { ...@@ -133,11 +133,56 @@ static struct kvm_events_ops ioport_events = {
.name = "IO Port Access" .name = "IO Port Access"
}; };
/* The time of emulation msr is from kvm_msr to kvm_entry. */
static void msr_event_get_key(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
key->key = evsel__intval(evsel, sample, "ecx");
key->info = evsel__intval(evsel, sample, "write");
}
static bool msr_event_begin(struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
if (!strcmp(evsel->name, "kvm:kvm_msr")) {
msr_event_get_key(evsel, sample, key);
return true;
}
return false;
}
static bool msr_event_end(struct evsel *evsel,
struct perf_sample *sample __maybe_unused,
struct event_key *key __maybe_unused)
{
return kvm_entry_event(evsel);
}
static void msr_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
struct event_key *key,
char *decode)
{
scnprintf(decode, decode_str_len, "%#llx:%s",
(unsigned long long)key->key,
key->info ? "W" : "R");
}
static struct kvm_events_ops msr_events = {
.is_begin_event = msr_event_begin,
.is_end_event = msr_event_end,
.decode_key = msr_event_decode_key,
.name = "MSR Access"
};
const char *kvm_events_tp[] = { const char *kvm_events_tp[] = {
"kvm:kvm_entry", "kvm:kvm_entry",
"kvm:kvm_exit", "kvm:kvm_exit",
"kvm:kvm_mmio", "kvm:kvm_mmio",
"kvm:kvm_pio", "kvm:kvm_pio",
"kvm:kvm_msr",
NULL, NULL,
}; };
...@@ -145,6 +190,7 @@ struct kvm_reg_events_ops kvm_reg_events_ops[] = { ...@@ -145,6 +190,7 @@ struct kvm_reg_events_ops kvm_reg_events_ops[] = {
{ .name = "vmexit", .ops = &exit_events }, { .name = "vmexit", .ops = &exit_events },
{ .name = "mmio", .ops = &mmio_events }, { .name = "mmio", .ops = &mmio_events },
{ .name = "ioport", .ops = &ioport_events }, { .name = "ioport", .ops = &ioport_events },
{ .name = "msr", .ops = &msr_events },
{ NULL, NULL }, { NULL, NULL },
}; };
......
...@@ -5,19 +5,41 @@ ...@@ -5,19 +5,41 @@
static char mem_loads_name[100]; static char mem_loads_name[100];
static bool mem_loads_name__init; static bool mem_loads_name__init;
static char mem_stores_name[100];
#define MEM_LOADS_AUX 0x8203 #define MEM_LOADS_AUX 0x8203
#define MEM_LOADS_AUX_NAME "{cpu/mem-loads-aux/,cpu/mem-loads,ldlat=%u/pp}:S" #define MEM_LOADS_AUX_NAME "{%s/mem-loads-aux/,%s/mem-loads,ldlat=%u/}:P"
#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("ldlat-loads", "%s/mem-loads,ldlat=%u/P", "%s/events/mem-loads"),
E("ldlat-stores", "%s/mem-stores/P", "%s/events/mem-stores"),
E(NULL, NULL, NULL),
};
struct perf_mem_event *perf_mem_events__ptr(int i)
{
if (i >= PERF_MEM_EVENTS__MAX)
return NULL;
return &perf_mem_events[i];
}
bool is_mem_loads_aux_event(struct evsel *leader) bool is_mem_loads_aux_event(struct evsel *leader)
{ {
if (!pmu_have_event("cpu", "mem-loads-aux")) if (perf_pmu__find("cpu")) {
return false; if (!pmu_have_event("cpu", "mem-loads-aux"))
return false;
} else if (perf_pmu__find("cpu_core")) {
if (!pmu_have_event("cpu_core", "mem-loads-aux"))
return false;
}
return leader->core.attr.config == MEM_LOADS_AUX; return leader->core.attr.config == MEM_LOADS_AUX;
} }
char *perf_mem_events__name(int i) char *perf_mem_events__name(int i, char *pmu_name)
{ {
struct perf_mem_event *e = perf_mem_events__ptr(i); struct perf_mem_event *e = perf_mem_events__ptr(i);
...@@ -25,20 +47,34 @@ char *perf_mem_events__name(int i) ...@@ -25,20 +47,34 @@ char *perf_mem_events__name(int i)
return NULL; return NULL;
if (i == PERF_MEM_EVENTS__LOAD) { if (i == PERF_MEM_EVENTS__LOAD) {
if (mem_loads_name__init) if (mem_loads_name__init && !pmu_name)
return mem_loads_name; return mem_loads_name;
mem_loads_name__init = true; if (!pmu_name) {
mem_loads_name__init = true;
pmu_name = (char *)"cpu";
}
if (pmu_have_event("cpu", "mem-loads-aux")) { if (pmu_have_event(pmu_name, "mem-loads-aux")) {
scnprintf(mem_loads_name, sizeof(mem_loads_name), scnprintf(mem_loads_name, sizeof(mem_loads_name),
MEM_LOADS_AUX_NAME, perf_mem_events__loads_ldlat); MEM_LOADS_AUX_NAME, pmu_name, pmu_name,
perf_mem_events__loads_ldlat);
} else { } else {
scnprintf(mem_loads_name, sizeof(mem_loads_name), scnprintf(mem_loads_name, sizeof(mem_loads_name),
e->name, perf_mem_events__loads_ldlat); e->name, pmu_name,
perf_mem_events__loads_ldlat);
} }
return mem_loads_name; return mem_loads_name;
} }
if (i == PERF_MEM_EVENTS__STORE) {
if (!pmu_name)
pmu_name = (char *)"cpu";
scnprintf(mem_stores_name, sizeof(mem_stores_name),
e->name, pmu_name);
return mem_stores_name;
}
return (char *)e->name; return (char *)e->name;
} }
...@@ -474,6 +474,9 @@ int cmd_annotate(int argc, const char **argv) ...@@ -474,6 +474,9 @@ int cmd_annotate(int argc, const char **argv)
.attr = perf_event__process_attr, .attr = perf_event__process_attr,
.build_id = perf_event__process_build_id, .build_id = perf_event__process_build_id,
.tracing_data = perf_event__process_tracing_data, .tracing_data = perf_event__process_tracing_data,
.id_index = perf_event__process_id_index,
.auxtrace_info = perf_event__process_auxtrace_info,
.auxtrace = perf_event__process_auxtrace,
.feature = process_feature_event, .feature = process_feature_event,
.ordered_events = true, .ordered_events = true,
.ordering_requires_timestamps = true, .ordering_requires_timestamps = true,
...@@ -483,6 +486,9 @@ int cmd_annotate(int argc, const char **argv) ...@@ -483,6 +486,9 @@ int cmd_annotate(int argc, const char **argv)
struct perf_data data = { struct perf_data data = {
.mode = PERF_DATA_MODE_READ, .mode = PERF_DATA_MODE_READ,
}; };
struct itrace_synth_opts itrace_synth_opts = {
.set = 0,
};
struct option options[] = { struct option options[] = {
OPT_STRING('i', "input", &input_name, "file", OPT_STRING('i', "input", &input_name, "file",
"input file name"), "input file name"),
...@@ -547,6 +553,9 @@ int cmd_annotate(int argc, const char **argv) ...@@ -547,6 +553,9 @@ int cmd_annotate(int argc, const char **argv)
OPT_CALLBACK(0, "percent-type", &annotate.opts, "local-period", OPT_CALLBACK(0, "percent-type", &annotate.opts, "local-period",
"Set percent type local/global-period/hits", "Set percent type local/global-period/hits",
annotate_parse_percent_type), annotate_parse_percent_type),
OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
"Instruction Tracing options\n" ITRACE_HELP,
itrace_parse_synth_opts),
OPT_END() OPT_END()
}; };
...@@ -591,6 +600,8 @@ int cmd_annotate(int argc, const char **argv) ...@@ -591,6 +600,8 @@ int cmd_annotate(int argc, const char **argv)
if (IS_ERR(annotate.session)) if (IS_ERR(annotate.session))
return PTR_ERR(annotate.session); return PTR_ERR(annotate.session);
annotate.session->itrace_synth_opts = &itrace_synth_opts;
annotate.has_br_stack = perf_header__has_feat(&annotate.session->header, annotate.has_br_stack = perf_header__has_feat(&annotate.session->header,
HEADER_BRANCH_STACK); HEADER_BRANCH_STACK);
......
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#include "ui/ui.h" #include "ui/ui.h"
#include "ui/progress.h" #include "ui/progress.h"
#include "../perf.h" #include "../perf.h"
#include "pmu.h"
#include "pmu-hybrid.h"
struct c2c_hists { struct c2c_hists {
struct hists hists; struct hists hists;
...@@ -2907,8 +2909,9 @@ static const char * const *record_mem_usage = __usage_record; ...@@ -2907,8 +2909,9 @@ static const char * const *record_mem_usage = __usage_record;
static int perf_c2c__record(int argc, const char **argv) static int perf_c2c__record(int argc, const char **argv)
{ {
int rec_argc, i = 0, j; int rec_argc, i = 0, j, rec_tmp_nr = 0;
const char **rec_argv; const char **rec_argv;
char **rec_tmp;
int ret; int ret;
bool all_user = false, all_kernel = false; bool all_user = false, all_kernel = false;
bool event_set = false; bool event_set = false;
...@@ -2932,11 +2935,21 @@ static int perf_c2c__record(int argc, const char **argv) ...@@ -2932,11 +2935,21 @@ static int perf_c2c__record(int argc, const char **argv)
argc = parse_options(argc, argv, options, record_mem_usage, argc = parse_options(argc, argv, options, record_mem_usage,
PARSE_OPT_KEEP_UNKNOWN); PARSE_OPT_KEEP_UNKNOWN);
rec_argc = argc + 11; /* max number of arguments */ if (!perf_pmu__has_hybrid())
rec_argc = argc + 11; /* max number of arguments */
else
rec_argc = argc + 11 * perf_pmu__hybrid_pmu_num();
rec_argv = calloc(rec_argc + 1, sizeof(char *)); rec_argv = calloc(rec_argc + 1, sizeof(char *));
if (!rec_argv) if (!rec_argv)
return -1; return -1;
rec_tmp = calloc(rec_argc + 1, sizeof(char *));
if (!rec_tmp) {
free(rec_argv);
return -1;
}
rec_argv[i++] = "record"; rec_argv[i++] = "record";
if (!event_set) { if (!event_set) {
...@@ -2964,21 +2977,9 @@ static int perf_c2c__record(int argc, const char **argv) ...@@ -2964,21 +2977,9 @@ static int perf_c2c__record(int argc, const char **argv)
rec_argv[i++] = "--phys-data"; rec_argv[i++] = "--phys-data";
rec_argv[i++] = "--sample-cpu"; rec_argv[i++] = "--sample-cpu";
for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { ret = perf_mem_events__record_args(rec_argv, &i, rec_tmp, &rec_tmp_nr);
e = perf_mem_events__ptr(j); if (ret)
if (!e->record) goto out;
continue;
if (!e->supported) {
pr_err("failed: event '%s' not supported\n",
perf_mem_events__name(j));
free(rec_argv);
return -1;
}
rec_argv[i++] = "-e";
rec_argv[i++] = perf_mem_events__name(j);
}
if (all_user) if (all_user)
rec_argv[i++] = "--all-user"; rec_argv[i++] = "--all-user";
...@@ -3002,6 +3003,11 @@ static int perf_c2c__record(int argc, const char **argv) ...@@ -3002,6 +3003,11 @@ static int perf_c2c__record(int argc, const char **argv)
} }
ret = cmd_record(i, rec_argv); ret = cmd_record(i, rec_argv);
out:
for (i = 0; i < rec_tmp_nr; i++)
free(rec_tmp[i]);
free(rec_tmp);
free(rec_argv); free(rec_argv);
return ret; return ret;
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */ #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
#include <linux/list.h> #include <linux/list.h>
#include <linux/string.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
...@@ -43,6 +44,8 @@ struct perf_inject { ...@@ -43,6 +44,8 @@ struct perf_inject {
bool have_auxtrace; bool have_auxtrace;
bool strip; bool strip;
bool jit_mode; bool jit_mode;
bool in_place_update;
bool in_place_update_dry_run;
const char *input_name; const char *input_name;
struct perf_data output; struct perf_data output;
u64 bytes_written; u64 bytes_written;
...@@ -380,8 +383,8 @@ static int perf_event__repipe_buildid_mmap(struct perf_tool *tool, ...@@ -380,8 +383,8 @@ static int perf_event__repipe_buildid_mmap(struct perf_tool *tool,
if (dso && !dso->hit) { if (dso && !dso->hit) {
dso->hit = 1; dso->hit = 1;
dso__inject_build_id(dso, tool, machine, sample->cpumode, 0); dso__inject_build_id(dso, tool, machine, sample->cpumode, 0);
dso__put(dso);
} }
dso__put(dso);
return perf_event__repipe(tool, event, sample, machine); return perf_event__repipe(tool, event, sample, machine);
} }
...@@ -396,6 +399,18 @@ static int perf_event__repipe_mmap2(struct perf_tool *tool, ...@@ -396,6 +399,18 @@ static int perf_event__repipe_mmap2(struct perf_tool *tool,
err = perf_event__process_mmap2(tool, event, sample, machine); err = perf_event__process_mmap2(tool, event, sample, machine);
perf_event__repipe(tool, event, sample, machine); perf_event__repipe(tool, event, sample, machine);
if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) {
struct dso *dso;
dso = findnew_dso(event->mmap2.pid, event->mmap2.tid,
event->mmap2.filename, NULL, machine);
if (dso) {
/* mark it not to inject build-id */
dso->hit = 1;
}
dso__put(dso);
}
return err; return err;
} }
...@@ -437,6 +452,18 @@ static int perf_event__repipe_buildid_mmap2(struct perf_tool *tool, ...@@ -437,6 +452,18 @@ static int perf_event__repipe_buildid_mmap2(struct perf_tool *tool,
}; };
struct dso *dso; struct dso *dso;
if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) {
/* cannot use dso_id since it'd have invalid info */
dso = findnew_dso(event->mmap2.pid, event->mmap2.tid,
event->mmap2.filename, NULL, machine);
if (dso) {
/* mark it not to inject build-id */
dso->hit = 1;
}
dso__put(dso);
return 0;
}
dso = findnew_dso(event->mmap2.pid, event->mmap2.tid, dso = findnew_dso(event->mmap2.pid, event->mmap2.tid,
event->mmap2.filename, &dso_id, machine); event->mmap2.filename, &dso_id, machine);
...@@ -444,8 +471,8 @@ static int perf_event__repipe_buildid_mmap2(struct perf_tool *tool, ...@@ -444,8 +471,8 @@ static int perf_event__repipe_buildid_mmap2(struct perf_tool *tool,
dso->hit = 1; dso->hit = 1;
dso__inject_build_id(dso, tool, machine, sample->cpumode, dso__inject_build_id(dso, tool, machine, sample->cpumode,
event->mmap2.flags); event->mmap2.flags);
dso__put(dso);
} }
dso__put(dso);
perf_event__repipe(tool, event, sample, machine); perf_event__repipe(tool, event, sample, machine);
...@@ -696,12 +723,42 @@ static void strip_init(struct perf_inject *inject) ...@@ -696,12 +723,42 @@ static void strip_init(struct perf_inject *inject)
evsel->handler = drop_sample; evsel->handler = drop_sample;
} }
static int parse_vm_time_correlation(const struct option *opt, const char *str, int unset)
{
struct perf_inject *inject = opt->value;
const char *args;
char *dry_run;
if (unset)
return 0;
inject->itrace_synth_opts.set = true;
inject->itrace_synth_opts.vm_time_correlation = true;
inject->in_place_update = true;
if (!str)
return 0;
dry_run = skip_spaces(str);
if (!strncmp(dry_run, "dry-run", strlen("dry-run"))) {
inject->itrace_synth_opts.vm_tm_corr_dry_run = true;
inject->in_place_update_dry_run = true;
args = dry_run + strlen("dry-run");
} else {
args = str;
}
inject->itrace_synth_opts.vm_tm_corr_args = strdup(args);
return inject->itrace_synth_opts.vm_tm_corr_args ? 0 : -ENOMEM;
}
static int __cmd_inject(struct perf_inject *inject) static int __cmd_inject(struct perf_inject *inject)
{ {
int ret = -EINVAL; int ret = -EINVAL;
struct perf_session *session = inject->session; struct perf_session *session = inject->session;
struct perf_data *data_out = &inject->output; struct perf_data *data_out = &inject->output;
int fd = perf_data__fd(data_out); int fd = inject->in_place_update ? -1 : perf_data__fd(data_out);
u64 output_data_offset; u64 output_data_offset;
signal(SIGINT, sig_handler); signal(SIGINT, sig_handler);
...@@ -737,6 +794,15 @@ static int __cmd_inject(struct perf_inject *inject) ...@@ -737,6 +794,15 @@ static int __cmd_inject(struct perf_inject *inject)
else if (!strncmp(name, "sched:sched_stat_", 17)) else if (!strncmp(name, "sched:sched_stat_", 17))
evsel->handler = perf_inject__sched_stat; evsel->handler = perf_inject__sched_stat;
} }
} else if (inject->itrace_synth_opts.vm_time_correlation) {
session->itrace_synth_opts = &inject->itrace_synth_opts;
memset(&inject->tool, 0, sizeof(inject->tool));
inject->tool.id_index = perf_event__process_id_index;
inject->tool.auxtrace_info = perf_event__process_auxtrace_info;
inject->tool.auxtrace = perf_event__process_auxtrace;
inject->tool.auxtrace_error = perf_event__process_auxtrace_error;
inject->tool.ordered_events = true;
inject->tool.ordering_requires_timestamps = true;
} else if (inject->itrace_synth_opts.set) { } else if (inject->itrace_synth_opts.set) {
session->itrace_synth_opts = &inject->itrace_synth_opts; session->itrace_synth_opts = &inject->itrace_synth_opts;
inject->itrace_synth_opts.inject = true; inject->itrace_synth_opts.inject = true;
...@@ -759,14 +825,14 @@ static int __cmd_inject(struct perf_inject *inject) ...@@ -759,14 +825,14 @@ static int __cmd_inject(struct perf_inject *inject)
if (!inject->itrace_synth_opts.set) if (!inject->itrace_synth_opts.set)
auxtrace_index__free(&session->auxtrace_index); auxtrace_index__free(&session->auxtrace_index);
if (!data_out->is_pipe) if (!data_out->is_pipe && !inject->in_place_update)
lseek(fd, output_data_offset, SEEK_SET); lseek(fd, output_data_offset, SEEK_SET);
ret = perf_session__process_events(session); ret = perf_session__process_events(session);
if (ret) if (ret)
return ret; return ret;
if (!data_out->is_pipe) { if (!data_out->is_pipe && !inject->in_place_update) {
if (inject->build_ids) if (inject->build_ids)
perf_header__set_feat(&session->header, perf_header__set_feat(&session->header,
HEADER_BUILD_ID); HEADER_BUILD_ID);
...@@ -878,6 +944,9 @@ int cmd_inject(int argc, const char **argv) ...@@ -878,6 +944,9 @@ int cmd_inject(int argc, const char **argv)
itrace_parse_synth_opts), itrace_parse_synth_opts),
OPT_BOOLEAN(0, "strip", &inject.strip, OPT_BOOLEAN(0, "strip", &inject.strip,
"strip non-synthesized events (use with --itrace)"), "strip non-synthesized events (use with --itrace)"),
OPT_CALLBACK_OPTARG(0, "vm-time-correlation", &inject, NULL, "opts",
"correlate time between VM guests and the host",
parse_vm_time_correlation),
OPT_END() OPT_END()
}; };
const char * const inject_usage[] = { const char * const inject_usage[] = {
...@@ -900,7 +969,23 @@ int cmd_inject(int argc, const char **argv) ...@@ -900,7 +969,23 @@ int cmd_inject(int argc, const char **argv)
return -1; return -1;
} }
if (perf_data__open(&inject.output)) { if (inject.in_place_update) {
if (!strcmp(inject.input_name, "-")) {
pr_err("Input file name required for in-place updating\n");
return -1;
}
if (strcmp(inject.output.path, "-")) {
pr_err("Output file name must not be specified for in-place updating\n");
return -1;
}
if (!data.force && !inject.in_place_update_dry_run) {
pr_err("The input file would be updated in place, "
"the --force option is required.\n");
return -1;
}
if (!inject.in_place_update_dry_run)
data.in_place_update = true;
} else if (perf_data__open(&inject.output)) {
perror("failed to create output file"); perror("failed to create output file");
return -1; return -1;
} }
...@@ -950,5 +1035,6 @@ int cmd_inject(int argc, const char **argv) ...@@ -950,5 +1035,6 @@ int cmd_inject(int argc, const char **argv)
out_delete: out_delete:
zstd_fini(&(inject.session->zstd_data)); zstd_fini(&(inject.session->zstd_data));
perf_session__delete(inject.session); perf_session__delete(inject.session);
free(inject.itrace_synth_opts.vm_tm_corr_args);
return ret; return ret;
} }
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include "util/dso.h" #include "util/dso.h"
#include "util/map.h" #include "util/map.h"
#include "util/symbol.h" #include "util/symbol.h"
#include "util/pmu.h"
#include "util/pmu-hybrid.h"
#include <linux/err.h> #include <linux/err.h>
#define MEM_OPERATION_LOAD 0x1 #define MEM_OPERATION_LOAD 0x1
...@@ -62,8 +64,10 @@ static const char * const *record_mem_usage = __usage; ...@@ -62,8 +64,10 @@ static const char * const *record_mem_usage = __usage;
static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
{ {
int rec_argc, i = 0, j; int rec_argc, i = 0, j, tmp_nr = 0;
int start, end;
const char **rec_argv; const char **rec_argv;
char **rec_tmp;
int ret; int ret;
bool all_user = false, all_kernel = false; bool all_user = false, all_kernel = false;
struct perf_mem_event *e; struct perf_mem_event *e;
...@@ -87,11 +91,24 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) ...@@ -87,11 +91,24 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
argc = parse_options(argc, argv, options, record_mem_usage, argc = parse_options(argc, argv, options, record_mem_usage,
PARSE_OPT_KEEP_UNKNOWN); PARSE_OPT_KEEP_UNKNOWN);
rec_argc = argc + 9; /* max number of arguments */ if (!perf_pmu__has_hybrid())
rec_argc = argc + 9; /* max number of arguments */
else
rec_argc = argc + 9 * perf_pmu__hybrid_pmu_num();
rec_argv = calloc(rec_argc + 1, sizeof(char *)); rec_argv = calloc(rec_argc + 1, sizeof(char *));
if (!rec_argv) if (!rec_argv)
return -1; return -1;
/*
* Save the allocated event name strings.
*/
rec_tmp = calloc(rec_argc + 1, sizeof(char *));
if (!rec_tmp) {
free(rec_argv);
return -1;
}
rec_argv[i++] = "record"; rec_argv[i++] = "record";
e = perf_mem_events__ptr(PERF_MEM_EVENTS__LOAD_STORE); e = perf_mem_events__ptr(PERF_MEM_EVENTS__LOAD_STORE);
...@@ -128,21 +145,11 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) ...@@ -128,21 +145,11 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
if (mem->data_page_size) if (mem->data_page_size)
rec_argv[i++] = "--data-page-size"; rec_argv[i++] = "--data-page-size";
for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { start = i;
e = perf_mem_events__ptr(j); ret = perf_mem_events__record_args(rec_argv, &i, rec_tmp, &tmp_nr);
if (!e->record) if (ret)
continue; goto out;
end = i;
if (!e->supported) {
pr_err("failed: event '%s' not supported\n",
perf_mem_events__name(j));
free(rec_argv);
return -1;
}
rec_argv[i++] = "-e";
rec_argv[i++] = perf_mem_events__name(j);
}
if (all_user) if (all_user)
rec_argv[i++] = "--all-user"; rec_argv[i++] = "--all-user";
...@@ -156,14 +163,18 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) ...@@ -156,14 +163,18 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
if (verbose > 0) { if (verbose > 0) {
pr_debug("calling: record "); pr_debug("calling: record ");
while (rec_argv[j]) { for (j = start; j < end; j++)
pr_debug("%s ", rec_argv[j]); pr_debug("%s ", rec_argv[j]);
j++;
}
pr_debug("\n"); pr_debug("\n");
} }
ret = cmd_record(i, rec_argv); ret = cmd_record(i, rec_argv);
out:
for (i = 0; i < tmp_nr; i++)
free(rec_tmp[i]);
free(rec_tmp);
free(rec_argv); free(rec_argv);
return ret; return ret;
} }
......
...@@ -347,7 +347,10 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs) ...@@ -347,7 +347,10 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)
goto out_cleanup; goto out_cleanup;
if (params.command == 'D') { /* it shows definition */ if (params.command == 'D') { /* it shows definition */
ret = show_probe_trace_events(pevs, npevs); if (probe_conf.bootconfig)
ret = show_bootconfig_events(pevs, npevs);
else
ret = show_probe_trace_events(pevs, npevs);
goto out_cleanup; goto out_cleanup;
} }
...@@ -581,6 +584,8 @@ __cmd_probe(int argc, const char **argv) ...@@ -581,6 +584,8 @@ __cmd_probe(int argc, const char **argv)
"Look for files with symbols relative to this directory"), "Look for files with symbols relative to this directory"),
OPT_CALLBACK(0, "target-ns", NULL, "pid", OPT_CALLBACK(0, "target-ns", NULL, "pid",
"target pid for namespace contexts", opt_set_target_ns), "target pid for namespace contexts", opt_set_target_ns),
OPT_BOOLEAN(0, "bootconfig", &probe_conf.bootconfig,
"Output probe definition with bootconfig format"),
OPT_END() OPT_END()
}; };
int ret; int ret;
...@@ -692,6 +697,11 @@ __cmd_probe(int argc, const char **argv) ...@@ -692,6 +697,11 @@ __cmd_probe(int argc, const char **argv)
} }
break; break;
case 'D': case 'D':
if (probe_conf.bootconfig && params.uprobes) {
pr_err(" Error: --bootconfig doesn't support uprobes.\n");
return -EINVAL;
}
__fallthrough;
case 'a': case 'a':
/* Ensure the last given target is used */ /* Ensure the last given target is used */
......
...@@ -969,6 +969,15 @@ static int record__open(struct record *rec) ...@@ -969,6 +969,15 @@ static int record__open(struct record *rec)
return rc; return rc;
} }
static void set_timestamp_boundary(struct record *rec, u64 sample_time)
{
if (rec->evlist->first_sample_time == 0)
rec->evlist->first_sample_time = sample_time;
if (sample_time)
rec->evlist->last_sample_time = sample_time;
}
static int process_sample_event(struct perf_tool *tool, static int process_sample_event(struct perf_tool *tool,
union perf_event *event, union perf_event *event,
struct perf_sample *sample, struct perf_sample *sample,
...@@ -977,10 +986,7 @@ static int process_sample_event(struct perf_tool *tool, ...@@ -977,10 +986,7 @@ static int process_sample_event(struct perf_tool *tool,
{ {
struct record *rec = container_of(tool, struct record, tool); struct record *rec = container_of(tool, struct record, tool);
if (rec->evlist->first_sample_time == 0) set_timestamp_boundary(rec, sample->time);
rec->evlist->first_sample_time = sample->time;
rec->evlist->last_sample_time = sample->time;
if (rec->buildid_all) if (rec->buildid_all)
return 0; return 0;
...@@ -2402,6 +2408,17 @@ static int build_id__process_mmap2(struct perf_tool *tool, union perf_event *eve ...@@ -2402,6 +2408,17 @@ static int build_id__process_mmap2(struct perf_tool *tool, union perf_event *eve
return perf_event__process_mmap2(tool, event, sample, machine); return perf_event__process_mmap2(tool, event, sample, machine);
} }
static int process_timestamp_boundary(struct perf_tool *tool,
union perf_event *event __maybe_unused,
struct perf_sample *sample,
struct machine *machine __maybe_unused)
{
struct record *rec = container_of(tool, struct record, tool);
set_timestamp_boundary(rec, sample->time);
return 0;
}
/* /*
* XXX Ideally would be local to cmd_record() and passed to a record__new * XXX Ideally would be local to cmd_record() and passed to a record__new
* because we need to have access to it in record__exit, that is called * because we need to have access to it in record__exit, that is called
...@@ -2436,6 +2453,8 @@ static struct record record = { ...@@ -2436,6 +2453,8 @@ static struct record record = {
.namespaces = perf_event__process_namespaces, .namespaces = perf_event__process_namespaces,
.mmap = build_id__process_mmap, .mmap = build_id__process_mmap,
.mmap2 = build_id__process_mmap2, .mmap2 = build_id__process_mmap2,
.itrace_start = process_timestamp_boundary,
.aux = process_timestamp_boundary,
.ordered_events = true, .ordered_events = true,
}, },
}; };
......
...@@ -934,6 +934,8 @@ static int __cmd_report(struct report *rep) ...@@ -934,6 +934,8 @@ static int __cmd_report(struct report *rep)
return ret; return ret;
} }
evlist__check_mem_load_aux(session->evlist);
if (rep->stats_mode) if (rep->stats_mode)
return stats_print(rep); return stats_print(rep);
......
This diff is collapsed.
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "util/annotate.h" #include "util/annotate.h"
#include "util/bpf-event.h" #include "util/bpf-event.h"
#include "util/cgroup.h"
#include "util/config.h" #include "util/config.h"
#include "util/color.h" #include "util/color.h"
#include "util/dso.h" #include "util/dso.h"
...@@ -1558,6 +1559,8 @@ int cmd_top(int argc, const char **argv) ...@@ -1558,6 +1559,8 @@ int cmd_top(int argc, const char **argv)
OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"), OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"),
OPT_UINTEGER(0, "num-thread-synthesize", &top.nr_threads_synthesize, OPT_UINTEGER(0, "num-thread-synthesize", &top.nr_threads_synthesize,
"number of thread to run event synthesize"), "number of thread to run event synthesize"),
OPT_CALLBACK('G', "cgroup", &top.evlist, "name",
"monitor event in cgroup name only", parse_cgroups),
OPT_BOOLEAN(0, "namespaces", &opts->record_namespaces, OPT_BOOLEAN(0, "namespaces", &opts->record_namespaces,
"Record namespaces events"), "Record namespaces events"),
OPT_BOOLEAN(0, "all-cgroups", &opts->record_cgroup, OPT_BOOLEAN(0, "all-cgroups", &opts->record_cgroup,
...@@ -1646,6 +1649,11 @@ int cmd_top(int argc, const char **argv) ...@@ -1646,6 +1649,11 @@ int cmd_top(int argc, const char **argv)
goto out_delete_evlist; goto out_delete_evlist;
} }
if (nr_cgroups > 0 && opts->record_cgroup) {
pr_err("--cgroup and --all-cgroups cannot be used together\n");
goto out_delete_evlist;
}
if (opts->branch_stack && callchain_param.enabled) if (opts->branch_stack && callchain_param.enabled)
symbol_conf.show_branchflag_count = true; symbol_conf.show_branchflag_count = true;
......
This diff is collapsed.
This diff is collapsed.
[
{
"BriefDescription": "Counts all microcode FP assists.",
"CollectPEBSRecord": "2",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc1",
"EventName": "ASSISTS.FP",
"PEBScounters": "0,1,2,3,4,5,6,7",
"PublicDescription": "Counts all microcode Floating Point assists.",
"SampleAfterValue": "100003",
"Speculative": "1",
"UMask": "0x2"
},
{
"BriefDescription": "Counts 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.",
"CollectPEBSRecord": "2",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
"PEBScounters": "0,1,2,3,4,5,6,7",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts 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.",
"CollectPEBSRecord": "2",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
"PEBScounters": "0,1,2,3,4,5,6,7",
"SampleAfterValue": "100003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts 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.",
"CollectPEBSRecord": "2",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE",
"PEBScounters": "0,1,2,3,4,5,6,7",
"SampleAfterValue": "100003",
"UMask": "0x4"
},
{
"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 MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"CollectPEBSRecord": "2",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE",
"PEBScounters": "0,1,2,3,4,5,6,7",
"PublicDescription": "Counts 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.",
"SampleAfterValue": "100003",
"UMask": "0x8"
},
{
"BriefDescription": "Counts 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.",
"CollectPEBSRecord": "2",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE",
"PEBScounters": "0,1,2,3,4,5,6,7",
"SampleAfterValue": "100003",
"UMask": "0x10"
},
{
"BriefDescription": "Counts 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.",
"CollectPEBSRecord": "2",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE",
"PEBScounters": "0,1,2,3,4,5,6,7",
"SampleAfterValue": "100003",
"UMask": "0x20"
},
{
"BriefDescription": "Counts number of SSE/AVX computational 512-bit packed double 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 double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"CollectPEBSRecord": "2",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE",
"PEBScounters": "0,1,2,3,4,5,6,7",
"SampleAfterValue": "100003",
"UMask": "0x40"
},
{
"BriefDescription": "Counts number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.",
"CollectPEBSRecord": "2",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE",
"PEBScounters": "0,1,2,3,4,5,6,7",
"SampleAfterValue": "100003",
"UMask": "0x80"
}
]
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
[
{
"BriefDescription": "Clockticks of the power control unit (PCU)",
"Counter": "0,1,2,3",
"CounterType": "PGMABLE",
"EventName": "UNC_P_CLOCKTICKS",
"PerPkg": "1",
"Unit": "PCU"
}
]
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment