Commit ec2cb7a5 authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo-4.19-20180801' of...

Merge tag 'perf-core-for-mingo-4.19-20180801' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

perf trace: (Arnaldo Carvalho de Melo)

- Do not require --no-syscalls to suppress strace like output, i.e.

     # perf trace -e sched:*switch

  will show just sched:sched_switch events, not strace-like formatted
  syscall events, use --syscalls to get the previous behaviour.

  If instead:

     # perf trace

  is used, i.e. no events specified, then --syscalls is implied and
  system wide strace like formatting will be applied to all syscalls.

  The behaviour when just a syscall subset is used with '-e' is unchanged:

     # perf trace -e *sleep,sched:*switch

  will work as before: just the 'nanosleep' syscall will be strace-like
  formatted plus the sched:sched_switch tracepoint event, system wide.

- Allow string table generators to use a default header dir, allowing
  use of them without parameters to see the table it generates on
  stdout, e.g.:

    $ tools/perf/trace/beauty/kvm_ioctl.sh
    static const char *kvm_ioctl_cmds[] = {
        [0x00] = "GET_API_VERSION",
        [0x01] = "CREATE_VM",
        [0x02] = "GET_MSR_INDEX_LIST",
        [0x03] = "CHECK_EXTENSION",
<BIG SNIP>
        [0xe0] = "CREATE_DEVICE",
        [0xe1] = "SET_DEVICE_ATTR",
        [0xe2] = "GET_DEVICE_ATTR",
        [0xe3] = "HAS_DEVICE_ATTR",
    };
    $

  See 'ls tools/perf/trace/beauty/*.sh' to see the available string
  table generators.

- Add a generator for IPPROTO_ socket's protocol constants.

perf record: (Kan Liang)

- Fix error out while applying initial delay and using LBR, due to
  the use of a PERF_TYPE_SOFTWARE/PERF_COUNT_SW_DUMMY event to track
  PERF_RECORD_MMAP events while waiting for the initial delay. Such
  events fail when configured asking PERF_SAMPLE_BRANCH_STACK in
  perf_event_attr.sample_type.

perf c2c: (Jiri Olsa)

- Fix report crash for empty browser, when processing a perf.data file
  without events of interest, either because not asked for in
  'perf record' or because the workload didn't triggered such events.

perf list: (Michael Petlan)

- Align metric group description format with PMU event description.

perf tests: (Sandipan Das)

- Fix indexing when invoking subtests, which caused BPF tests to
  get results for the next test in the list, with the last one
  reporting a failure.

eBPF:

- Fix installation directory for header files included from eBPF proggies,
  avoiding clashing with relative paths used to build other software projects
  such as glibc. (Thomas Richter)

- Show better message when failing to load an object. (Arnaldo Carvalho de Melo)

General: (Christophe Leroy)

- Allow overriding MAX_NR_CPUS at compile time, to make the tooling
  usable in systems with less memory, in time this has to be changed
  to properly allocate based on _NPROCESSORS_ONLN.

Architecture specific:

- Update arm64's ThunderX2 implementation defined pmu core events (Ganapatrao Kulkarni)

- Fix complex event name parsing in 'perf test' for PowerPC, where the 'umask' event
  modifier isn't present. (Sandipan Das)

CoreSight ARM hardware tracing: (Leo Yan)

- Fix start tracing packet handling.

- Support dummy address value for CS_ETM_TRACE_ON packet.

- Generate branch sample when receiving a CS_ETM_TRACE_ON packet.

- Generate branch sample for CS_ETM_TRACE_ON packet.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 16e0e6a8 b912885a
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions of the Internet Protocol.
*
* Version: @(#)in.h 1.0.1 04/21/93
*
* Authors: Original taken from the GNU Project <netinet/in.h> file.
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _UAPI_LINUX_IN_H
#define _UAPI_LINUX_IN_H
#include <linux/types.h>
#include <linux/libc-compat.h>
#include <linux/socket.h>
#if __UAPI_DEF_IN_IPPROTO
/* Standard well-defined IP protocols. */
enum {
IPPROTO_IP = 0, /* Dummy protocol for TCP */
#define IPPROTO_IP IPPROTO_IP
IPPROTO_ICMP = 1, /* Internet Control Message Protocol */
#define IPPROTO_ICMP IPPROTO_ICMP
IPPROTO_IGMP = 2, /* Internet Group Management Protocol */
#define IPPROTO_IGMP IPPROTO_IGMP
IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */
#define IPPROTO_IPIP IPPROTO_IPIP
IPPROTO_TCP = 6, /* Transmission Control Protocol */
#define IPPROTO_TCP IPPROTO_TCP
IPPROTO_EGP = 8, /* Exterior Gateway Protocol */
#define IPPROTO_EGP IPPROTO_EGP
IPPROTO_PUP = 12, /* PUP protocol */
#define IPPROTO_PUP IPPROTO_PUP
IPPROTO_UDP = 17, /* User Datagram Protocol */
#define IPPROTO_UDP IPPROTO_UDP
IPPROTO_IDP = 22, /* XNS IDP protocol */
#define IPPROTO_IDP IPPROTO_IDP
IPPROTO_TP = 29, /* SO Transport Protocol Class 4 */
#define IPPROTO_TP IPPROTO_TP
IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol */
#define IPPROTO_DCCP IPPROTO_DCCP
IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */
#define IPPROTO_IPV6 IPPROTO_IPV6
IPPROTO_RSVP = 46, /* RSVP Protocol */
#define IPPROTO_RSVP IPPROTO_RSVP
IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */
#define IPPROTO_GRE IPPROTO_GRE
IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */
#define IPPROTO_ESP IPPROTO_ESP
IPPROTO_AH = 51, /* Authentication Header protocol */
#define IPPROTO_AH IPPROTO_AH
IPPROTO_MTP = 92, /* Multicast Transport Protocol */
#define IPPROTO_MTP IPPROTO_MTP
IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET */
#define IPPROTO_BEETPH IPPROTO_BEETPH
IPPROTO_ENCAP = 98, /* Encapsulation Header */
#define IPPROTO_ENCAP IPPROTO_ENCAP
IPPROTO_PIM = 103, /* Protocol Independent Multicast */
#define IPPROTO_PIM IPPROTO_PIM
IPPROTO_COMP = 108, /* Compression Header Protocol */
#define IPPROTO_COMP IPPROTO_COMP
IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */
#define IPPROTO_SCTP IPPROTO_SCTP
IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */
#define IPPROTO_UDPLITE IPPROTO_UDPLITE
IPPROTO_MPLS = 137, /* MPLS in IP (RFC 4023) */
#define IPPROTO_MPLS IPPROTO_MPLS
IPPROTO_RAW = 255, /* Raw IP packets */
#define IPPROTO_RAW IPPROTO_RAW
IPPROTO_MAX
};
#endif
#if __UAPI_DEF_IN_ADDR
/* Internet address. */
struct in_addr {
__be32 s_addr;
};
#endif
#define IP_TOS 1
#define IP_TTL 2
#define IP_HDRINCL 3
#define IP_OPTIONS 4
#define IP_ROUTER_ALERT 5
#define IP_RECVOPTS 6
#define IP_RETOPTS 7
#define IP_PKTINFO 8
#define IP_PKTOPTIONS 9
#define IP_MTU_DISCOVER 10
#define IP_RECVERR 11
#define IP_RECVTTL 12
#define IP_RECVTOS 13
#define IP_MTU 14
#define IP_FREEBIND 15
#define IP_IPSEC_POLICY 16
#define IP_XFRM_POLICY 17
#define IP_PASSSEC 18
#define IP_TRANSPARENT 19
/* BSD compatibility */
#define IP_RECVRETOPTS IP_RETOPTS
/* TProxy original addresses */
#define IP_ORIGDSTADDR 20
#define IP_RECVORIGDSTADDR IP_ORIGDSTADDR
#define IP_MINTTL 21
#define IP_NODEFRAG 22
#define IP_CHECKSUM 23
#define IP_BIND_ADDRESS_NO_PORT 24
#define IP_RECVFRAGSIZE 25
/* IP_MTU_DISCOVER values */
#define IP_PMTUDISC_DONT 0 /* Never send DF frames */
#define IP_PMTUDISC_WANT 1 /* Use per route hints */
#define IP_PMTUDISC_DO 2 /* Always DF */
#define IP_PMTUDISC_PROBE 3 /* Ignore dst pmtu */
/* Always use interface mtu (ignores dst pmtu) but don't set DF flag.
* Also incoming ICMP frag_needed notifications will be ignored on
* this socket to prevent accepting spoofed ones.
*/
#define IP_PMTUDISC_INTERFACE 4
/* weaker version of IP_PMTUDISC_INTERFACE, which allos packets to get
* fragmented if they exeed the interface mtu
*/
#define IP_PMTUDISC_OMIT 5
#define IP_MULTICAST_IF 32
#define IP_MULTICAST_TTL 33
#define IP_MULTICAST_LOOP 34
#define IP_ADD_MEMBERSHIP 35
#define IP_DROP_MEMBERSHIP 36
#define IP_UNBLOCK_SOURCE 37
#define IP_BLOCK_SOURCE 38
#define IP_ADD_SOURCE_MEMBERSHIP 39
#define IP_DROP_SOURCE_MEMBERSHIP 40
#define IP_MSFILTER 41
#define MCAST_JOIN_GROUP 42
#define MCAST_BLOCK_SOURCE 43
#define MCAST_UNBLOCK_SOURCE 44
#define MCAST_LEAVE_GROUP 45
#define MCAST_JOIN_SOURCE_GROUP 46
#define MCAST_LEAVE_SOURCE_GROUP 47
#define MCAST_MSFILTER 48
#define IP_MULTICAST_ALL 49
#define IP_UNICAST_IF 50
#define MCAST_EXCLUDE 0
#define MCAST_INCLUDE 1
/* These need to appear somewhere around here */
#define IP_DEFAULT_MULTICAST_TTL 1
#define IP_DEFAULT_MULTICAST_LOOP 1
/* Request struct for multicast socket ops */
#if __UAPI_DEF_IP_MREQ
struct ip_mreq {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};
struct ip_mreqn {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_address; /* local IP address of interface */
int imr_ifindex; /* Interface index */
};
struct ip_mreq_source {
__be32 imr_multiaddr;
__be32 imr_interface;
__be32 imr_sourceaddr;
};
struct ip_msfilter {
__be32 imsf_multiaddr;
__be32 imsf_interface;
__u32 imsf_fmode;
__u32 imsf_numsrc;
__be32 imsf_slist[1];
};
#define IP_MSFILTER_SIZE(numsrc) \
(sizeof(struct ip_msfilter) - sizeof(__u32) \
+ (numsrc) * sizeof(__u32))
struct group_req {
__u32 gr_interface; /* interface index */
struct __kernel_sockaddr_storage gr_group; /* group address */
};
struct group_source_req {
__u32 gsr_interface; /* interface index */
struct __kernel_sockaddr_storage gsr_group; /* group address */
struct __kernel_sockaddr_storage gsr_source; /* source address */
};
struct group_filter {
__u32 gf_interface; /* interface index */
struct __kernel_sockaddr_storage gf_group; /* multicast address */
__u32 gf_fmode; /* filter mode */
__u32 gf_numsrc; /* number of sources */
struct __kernel_sockaddr_storage gf_slist[1]; /* interface index */
};
#define GROUP_FILTER_SIZE(numsrc) \
(sizeof(struct group_filter) - sizeof(struct __kernel_sockaddr_storage) \
+ (numsrc) * sizeof(struct __kernel_sockaddr_storage))
#endif
#if __UAPI_DEF_IN_PKTINFO
struct in_pktinfo {
int ipi_ifindex;
struct in_addr ipi_spec_dst;
struct in_addr ipi_addr;
};
#endif
/* Structure describing an Internet (IP) socket address. */
#if __UAPI_DEF_SOCKADDR_IN
#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
struct sockaddr_in {
__kernel_sa_family_t sin_family; /* Address family */
__be16 sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
/* Pad to size of `struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};
#define sin_zero __pad /* for BSD UNIX comp. -FvK */
#endif
#if __UAPI_DEF_IN_CLASS
/*
* Definitions of the bits in an Internet address integer.
* On subnets, host and network parts are found according
* to the subnet mask, not these masks.
*/
#define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0)
#define IN_CLASSA_NET 0xff000000
#define IN_CLASSA_NSHIFT 24
#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET)
#define IN_CLASSA_MAX 128
#define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000)
#define IN_CLASSB_NET 0xffff0000
#define IN_CLASSB_NSHIFT 16
#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET)
#define IN_CLASSB_MAX 65536
#define IN_CLASSC(a) ((((long int) (a)) & 0xe0000000) == 0xc0000000)
#define IN_CLASSC_NET 0xffffff00
#define IN_CLASSC_NSHIFT 8
#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET)
#define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000)
#define IN_MULTICAST(a) IN_CLASSD(a)
#define IN_MULTICAST_NET 0xF0000000
#define IN_EXPERIMENTAL(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000)
#define IN_BADCLASS(a) IN_EXPERIMENTAL((a))
/* Address to accept any incoming messages. */
#define INADDR_ANY ((unsigned long int) 0x00000000)
/* Address to send to all hosts. */
#define INADDR_BROADCAST ((unsigned long int) 0xffffffff)
/* Address indicating an error return. */
#define INADDR_NONE ((unsigned long int) 0xffffffff)
/* Network number for local host loopback. */
#define IN_LOOPBACKNET 127
/* Address to loopback in software to local host. */
#define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */
#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000)
/* Defines for Multicast INADDR */
#define INADDR_UNSPEC_GROUP 0xe0000000U /* 224.0.0.0 */
#define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */
#define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */
#define INADDR_MAX_LOCAL_GROUP 0xe00000ffU /* 224.0.0.255 */
#endif
/* <asm/byteorder.h> contains the htonl type stuff.. */
#include <asm/byteorder.h>
#endif /* _UAPI_LINUX_IN_H */
...@@ -907,8 +907,8 @@ bindir = $(abspath $(prefix)/$(bindir_relative)) ...@@ -907,8 +907,8 @@ bindir = $(abspath $(prefix)/$(bindir_relative))
mandir = share/man mandir = share/man
infodir = share/info infodir = share/info
perfexecdir = libexec/perf-core perfexecdir = libexec/perf-core
perf_include_dir = lib/include/perf perf_include_dir = lib/perf/include
perf_examples_dir = lib/examples/perf perf_examples_dir = lib/perf/examples
sharedir = $(prefix)/share sharedir = $(prefix)/share
template_dir = share/perf-core/templates template_dir = share/perf-core/templates
STRACE_GROUPS_DIR = share/perf-core/strace/groups STRACE_GROUPS_DIR = share/perf-core/strace/groups
......
...@@ -384,6 +384,8 @@ export INSTALL SHELL_PATH ...@@ -384,6 +384,8 @@ export INSTALL SHELL_PATH
SHELL = $(SHELL_PATH) SHELL = $(SHELL_PATH)
linux_uapi_dir := $(srctree)/tools/include/uapi/linux
beauty_outdir := $(OUTPUT)trace/beauty/generated beauty_outdir := $(OUTPUT)trace/beauty/generated
beauty_ioctl_outdir := $(beauty_outdir)/ioctl beauty_ioctl_outdir := $(beauty_outdir)/ioctl
drm_ioctl_array := $(beauty_ioctl_outdir)/drm_ioctl_array.c drm_ioctl_array := $(beauty_ioctl_outdir)/drm_ioctl_array.c
...@@ -431,6 +433,12 @@ kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh ...@@ -431,6 +433,12 @@ kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh
$(kvm_ioctl_array): $(kvm_hdr_dir)/kvm.h $(kvm_ioctl_tbl) $(kvm_ioctl_array): $(kvm_hdr_dir)/kvm.h $(kvm_ioctl_tbl)
$(Q)$(SHELL) '$(kvm_ioctl_tbl)' $(kvm_hdr_dir) > $@ $(Q)$(SHELL) '$(kvm_ioctl_tbl)' $(kvm_hdr_dir) > $@
socket_ipproto_array := $(beauty_outdir)/socket_ipproto_array.c
socket_ipproto_tbl := $(srctree)/tools/perf/trace/beauty/socket_ipproto.sh
$(socket_ipproto_array): $(linux_uapi_dir)/in.h $(socket_ipproto_tbl)
$(Q)$(SHELL) '$(socket_ipproto_tbl)' $(linux_uapi_dir) > $@
vhost_virtio_ioctl_array := $(beauty_ioctl_outdir)/vhost_virtio_ioctl_array.c vhost_virtio_ioctl_array := $(beauty_ioctl_outdir)/vhost_virtio_ioctl_array.c
vhost_virtio_hdr_dir := $(srctree)/tools/include/uapi/linux vhost_virtio_hdr_dir := $(srctree)/tools/include/uapi/linux
vhost_virtio_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/vhost_virtio_ioctl.sh vhost_virtio_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
...@@ -566,6 +574,7 @@ prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioc ...@@ -566,6 +574,7 @@ prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioc
$(sndrv_ctl_ioctl_array) \ $(sndrv_ctl_ioctl_array) \
$(kcmp_type_array) \ $(kcmp_type_array) \
$(kvm_ioctl_array) \ $(kvm_ioctl_array) \
$(socket_ipproto_array) \
$(vhost_virtio_ioctl_array) \ $(vhost_virtio_ioctl_array) \
$(madvise_behavior_array) \ $(madvise_behavior_array) \
$(perf_ioctl_array) \ $(perf_ioctl_array) \
...@@ -860,6 +869,7 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea ...@@ -860,6 +869,7 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
$(OUTPUT)$(sndrv_pcm_ioctl_array) \ $(OUTPUT)$(sndrv_pcm_ioctl_array) \
$(OUTPUT)$(kvm_ioctl_array) \ $(OUTPUT)$(kvm_ioctl_array) \
$(OUTPUT)$(kcmp_type_array) \ $(OUTPUT)$(kcmp_type_array) \
$(OUTPUT)$(socket_ipproto_array) \
$(OUTPUT)$(vhost_virtio_ioctl_array) \ $(OUTPUT)$(vhost_virtio_ioctl_array) \
$(OUTPUT)$(perf_ioctl_array) \ $(OUTPUT)$(perf_ioctl_array) \
$(OUTPUT)$(prctl_option_array) \ $(OUTPUT)$(prctl_option_array) \
......
...@@ -2349,6 +2349,9 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he) ...@@ -2349,6 +2349,9 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he)
" s Toggle full length of symbol and source line columns \n" " s Toggle full length of symbol and source line columns \n"
" q Return back to cacheline list \n"; " q Return back to cacheline list \n";
if (!he)
return 0;
/* Display compact version first. */ /* Display compact version first. */
c2c.symbol_full = false; c2c.symbol_full = false;
......
...@@ -291,7 +291,7 @@ size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const cha ...@@ -291,7 +291,7 @@ size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const cha
{ {
int idx = val - sa->offset; int idx = val - sa->offset;
if (idx < 0 || idx >= sa->nr_entries) if (idx < 0 || idx >= sa->nr_entries || sa->entries[idx] == NULL)
return scnprintf(bf, size, intfmt, val); return scnprintf(bf, size, intfmt, val);
return scnprintf(bf, size, "%s", sa->entries[idx]); return scnprintf(bf, size, "%s", sa->entries[idx]);
...@@ -761,10 +761,12 @@ static struct syscall_fmt { ...@@ -761,10 +761,12 @@ static struct syscall_fmt {
.arg = { [0] = STRARRAY(resource, rlimit_resources), }, }, .arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
{ .name = "socket", { .name = "socket",
.arg = { [0] = STRARRAY(family, socket_families), .arg = { [0] = STRARRAY(family, socket_families),
[1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, }, [1] = { .scnprintf = SCA_SK_TYPE, /* type */ },
[2] = { .scnprintf = SCA_SK_PROTO, /* protocol */ }, }, },
{ .name = "socketpair", { .name = "socketpair",
.arg = { [0] = STRARRAY(family, socket_families), .arg = { [0] = STRARRAY(family, socket_families),
[1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, }, [1] = { .scnprintf = SCA_SK_TYPE, /* type */ },
[2] = { .scnprintf = SCA_SK_PROTO, /* protocol */ }, }, },
{ .name = "stat", .alias = "newstat", }, { .name = "stat", .alias = "newstat", },
{ .name = "statx", { .name = "statx",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fdat */ }, .arg = { [0] = { .scnprintf = SCA_FDAT, /* fdat */ },
...@@ -2990,6 +2992,7 @@ static int trace__parse_events_option(const struct option *opt, const char *str, ...@@ -2990,6 +2992,7 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
if (trace__validate_ev_qualifier(trace)) if (trace__validate_ev_qualifier(trace))
goto out; goto out;
trace->trace_syscalls = true;
} }
err = 0; err = 0;
...@@ -3045,7 +3048,7 @@ int cmd_trace(int argc, const char **argv) ...@@ -3045,7 +3048,7 @@ int cmd_trace(int argc, const char **argv)
}, },
.output = stderr, .output = stderr,
.show_comm = true, .show_comm = true,
.trace_syscalls = true, .trace_syscalls = false,
.kernel_syscallchains = false, .kernel_syscallchains = false,
.max_stack = UINT_MAX, .max_stack = UINT_MAX,
}; };
...@@ -3191,13 +3194,7 @@ int cmd_trace(int argc, const char **argv) ...@@ -3191,13 +3194,7 @@ int cmd_trace(int argc, const char **argv)
if (!trace.trace_syscalls && !trace.trace_pgfaults && if (!trace.trace_syscalls && !trace.trace_pgfaults &&
trace.evlist->nr_entries == 0 /* Was --events used? */) { trace.evlist->nr_entries == 0 /* Was --events used? */) {
pr_err("Please specify something to trace.\n"); trace.trace_syscalls = true;
return -1;
}
if (!trace.trace_syscalls && trace.ev_qualifier) {
pr_err("The -e option can't be used with --no-syscalls.\n");
goto out;
} }
if (output_name != NULL) { if (output_name != NULL) {
......
...@@ -7,6 +7,7 @@ include/uapi/drm/i915_drm.h ...@@ -7,6 +7,7 @@ include/uapi/drm/i915_drm.h
include/uapi/linux/fcntl.h include/uapi/linux/fcntl.h
include/uapi/linux/kcmp.h include/uapi/linux/kcmp.h
include/uapi/linux/kvm.h include/uapi/linux/kvm.h
include/uapi/linux/in.h
include/uapi/linux/perf_event.h include/uapi/linux/perf_event.h
include/uapi/linux/prctl.h include/uapi/linux/prctl.h
include/uapi/linux/sched.h include/uapi/linux/sched.h
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#ifndef _PERF_BPF_H #ifndef _PERF_BPF_H
#define _PERF_BPF_H #define _PERF_BPF_H
#include <uapi/linux/bpf.h>
#define SEC(NAME) __attribute__((section(NAME), used)) #define SEC(NAME) __attribute__((section(NAME), used))
#define probe(function, vars) \ #define probe(function, vars) \
......
...@@ -25,7 +25,9 @@ static inline unsigned long long rdclock(void) ...@@ -25,7 +25,9 @@ static inline unsigned long long rdclock(void)
return ts.tv_sec * 1000000000ULL + ts.tv_nsec; return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
} }
#ifndef MAX_NR_CPUS
#define MAX_NR_CPUS 1024 #define MAX_NR_CPUS 1024
#endif
extern const char *input_name; extern const char *input_name;
extern bool perf_host, perf_guest; extern bool perf_host, perf_guest;
......
...@@ -11,6 +11,21 @@ ...@@ -11,6 +11,21 @@
{ {
"ArchStdEvent": "L1D_CACHE_REFILL_WR", "ArchStdEvent": "L1D_CACHE_REFILL_WR",
}, },
{
"ArchStdEvent": "L1D_CACHE_REFILL_INNER",
},
{
"ArchStdEvent": "L1D_CACHE_REFILL_OUTER",
},
{
"ArchStdEvent": "L1D_CACHE_WB_VICTIM",
},
{
"ArchStdEvent": "L1D_CACHE_WB_CLEAN",
},
{
"ArchStdEvent": "L1D_CACHE_INVAL",
},
{ {
"ArchStdEvent": "L1D_TLB_REFILL_RD", "ArchStdEvent": "L1D_TLB_REFILL_RD",
}, },
...@@ -23,10 +38,76 @@ ...@@ -23,10 +38,76 @@
{ {
"ArchStdEvent": "L1D_TLB_WR", "ArchStdEvent": "L1D_TLB_WR",
}, },
{
"ArchStdEvent": "L2D_TLB_REFILL_RD",
},
{
"ArchStdEvent": "L2D_TLB_REFILL_WR",
},
{
"ArchStdEvent": "L2D_TLB_RD",
},
{
"ArchStdEvent": "L2D_TLB_WR",
},
{ {
"ArchStdEvent": "BUS_ACCESS_RD", "ArchStdEvent": "BUS_ACCESS_RD",
}, },
{ {
"ArchStdEvent": "BUS_ACCESS_WR", "ArchStdEvent": "BUS_ACCESS_WR",
} },
{
"ArchStdEvent": "MEM_ACCESS_RD",
},
{
"ArchStdEvent": "MEM_ACCESS_WR",
},
{
"ArchStdEvent": "UNALIGNED_LD_SPEC",
},
{
"ArchStdEvent": "UNALIGNED_ST_SPEC",
},
{
"ArchStdEvent": "UNALIGNED_LDST_SPEC",
},
{
"ArchStdEvent": "EXC_UNDEF",
},
{
"ArchStdEvent": "EXC_SVC",
},
{
"ArchStdEvent": "EXC_PABORT",
},
{
"ArchStdEvent": "EXC_DABORT",
},
{
"ArchStdEvent": "EXC_IRQ",
},
{
"ArchStdEvent": "EXC_FIQ",
},
{
"ArchStdEvent": "EXC_SMC",
},
{
"ArchStdEvent": "EXC_HVC",
},
{
"ArchStdEvent": "EXC_TRAP_PABORT",
},
{
"ArchStdEvent": "EXC_TRAP_DABORT",
},
{
"ArchStdEvent": "EXC_TRAP_OTHER",
},
{
"ArchStdEvent": "EXC_TRAP_IRQ",
},
{
"ArchStdEvent": "EXC_TRAP_FIQ",
}
] ]
...@@ -385,7 +385,7 @@ static int test_and_print(struct test *t, bool force_skip, int subtest) ...@@ -385,7 +385,7 @@ static int test_and_print(struct test *t, bool force_skip, int subtest)
if (!t->subtest.get_nr) if (!t->subtest.get_nr)
pr_debug("%s:", t->desc); pr_debug("%s:", t->desc);
else else
pr_debug("%s subtest %d:", t->desc, subtest); pr_debug("%s subtest %d:", t->desc, subtest + 1);
switch (err) { switch (err) {
case TEST_OK: case TEST_OK:
...@@ -599,7 +599,7 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) ...@@ -599,7 +599,7 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
for (subi = 0; subi < subn; subi++) { for (subi = 0; subi < subn; subi++) {
pr_info("%2d.%1d: %-*s:", i, subi + 1, subw, pr_info("%2d.%1d: %-*s:", i, subi + 1, subw,
t->subtest.get_desc(subi)); t->subtest.get_desc(subi));
err = test_and_print(t, skip, subi + 1); err = test_and_print(t, skip, subi);
if (err != TEST_OK && t->subtest.skip_if_fail) if (err != TEST_OK && t->subtest.skip_if_fail)
skip = true; skip = true;
} }
......
...@@ -1690,7 +1690,7 @@ static struct evlist_test test__events_pmu[] = { ...@@ -1690,7 +1690,7 @@ static struct evlist_test test__events_pmu[] = {
.id = 2, .id = 2,
}, },
{ {
.name = "cpu/name='COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks',period=0x1,event=0x2,umask=0x3/ukp", .name = "cpu/name='COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks',period=0x1,event=0x2/ukp",
.check = test__checkevent_complex_name, .check = test__checkevent_complex_name,
.id = 3, .id = 3,
} }
......
...@@ -7,4 +7,5 @@ endif ...@@ -7,4 +7,5 @@ endif
libperf-y += kcmp.o libperf-y += kcmp.o
libperf-y += pkey_alloc.o libperf-y += pkey_alloc.o
libperf-y += prctl.o libperf-y += prctl.o
libperf-y += socket.o
libperf-y += statx.o libperf-y += statx.o
...@@ -106,6 +106,9 @@ size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_a ...@@ -106,6 +106,9 @@ size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_a
size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg); size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_PRCTL_ARG3 syscall_arg__scnprintf_prctl_arg3 #define SCA_PRCTL_ARG3 syscall_arg__scnprintf_prctl_arg3
size_t syscall_arg__scnprintf_socket_protocol(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_SK_PROTO syscall_arg__scnprintf_socket_protocol
size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg); size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags #define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags
......
#!/bin/sh #!/bin/sh
drm_header_dir=$1 [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/drm/
printf "#ifndef DRM_COMMAND_BASE\n" printf "#ifndef DRM_COMMAND_BASE\n"
grep "#define DRM_COMMAND_BASE" $drm_header_dir/drm.h grep "#define DRM_COMMAND_BASE" $header_dir/drm.h
printf "#endif\n" printf "#endif\n"
printf "static const char *drm_ioctl_cmds[] = {\n" printf "static const char *drm_ioctl_cmds[] = {\n"
grep "^#define DRM_IOCTL.*DRM_IO" $drm_header_dir/drm.h | \ grep "^#define DRM_IOCTL.*DRM_IO" $header_dir/drm.h | \
sed -r 's/^#define +DRM_IOCTL_([A-Z0-9_]+)[ ]+DRM_IO[A-Z]* *\( *(0x[[:xdigit:]]+),*.*/ [\2] = "\1",/g' sed -r 's/^#define +DRM_IOCTL_([A-Z0-9_]+)[ ]+DRM_IO[A-Z]* *\( *(0x[[:xdigit:]]+),*.*/ [\2] = "\1",/g'
grep "^#define DRM_I915_[A-Z_0-9]\+[ ]\+0x" $drm_header_dir/i915_drm.h | \ grep "^#define DRM_I915_[A-Z_0-9]\+[ ]\+0x" $header_dir/i915_drm.h | \
sed -r 's/^#define +DRM_I915_([A-Z0-9_]+)[ ]+(0x[[:xdigit:]]+)/\t[DRM_COMMAND_BASE + \2] = "I915_\1",/g' sed -r 's/^#define +DRM_I915_([A-Z0-9_]+)[ ]+(0x[[:xdigit:]]+)/\t[DRM_COMMAND_BASE + \2] = "I915_\1",/g'
printf "};\n" printf "};\n"
#!/bin/sh #!/bin/sh
header_dir=$1 [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
printf "static const char *kcmp_types[] = {\n" printf "static const char *kcmp_types[] = {\n"
regex='^[[:space:]]+(KCMP_(\w+)),' regex='^[[:space:]]+(KCMP_(\w+)),'
......
#!/bin/sh #!/bin/sh
kvm_header_dir=$1 [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
printf "static const char *kvm_ioctl_cmds[] = {\n" printf "static const char *kvm_ioctl_cmds[] = {\n"
regex='^#[[:space:]]*define[[:space:]]+KVM_(\w+)[[:space:]]+_IO[RW]*\([[:space:]]*KVMIO[[:space:]]*,[[:space:]]*(0x[[:xdigit:]]+).*' regex='^#[[:space:]]*define[[:space:]]+KVM_(\w+)[[:space:]]+_IO[RW]*\([[:space:]]*KVMIO[[:space:]]*,[[:space:]]*(0x[[:xdigit:]]+).*'
egrep $regex ${kvm_header_dir}/kvm.h | \ egrep $regex ${header_dir}/kvm.h | \
sed -r "s/$regex/\2 \1/g" | \ sed -r "s/$regex/\2 \1/g" | \
egrep -v " ((ARM|PPC|S390)_|[GS]ET_(DEBUGREGS|PIT2|XSAVE|TSC_KHZ)|CREATE_SPAPR_TCE_64)" | \ egrep -v " ((ARM|PPC|S390)_|[GS]ET_(DEBUGREGS|PIT2|XSAVE|TSC_KHZ)|CREATE_SPAPR_TCE_64)" | \
sort | xargs printf "\t[%s] = \"%s\",\n" sort | xargs printf "\t[%s] = \"%s\",\n"
......
#!/bin/sh #!/bin/sh
header_dir=$1 [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/
printf "static const char *madvise_advices[] = {\n" printf "static const char *madvise_advices[] = {\n"
regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MADV_([[:alnum:]_]+)[[:space:]]+([[:digit:]]+)[[:space:]]*.*' regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MADV_([[:alnum:]_]+)[[:space:]]+([[:digit:]]+)[[:space:]]*.*'
......
#!/bin/sh #!/bin/sh
header_dir=$1 [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
printf "static const char *perf_ioctl_cmds[] = {\n" printf "static const char *perf_ioctl_cmds[] = {\n"
regex='^#[[:space:]]*define[[:space:]]+PERF_EVENT_IOC_(\w+)[[:space:]]+_IO[RW]*[[:space:]]*\([[:space:]]*.\$.[[:space:]]*,[[:space:]]*([[:digit:]]+).*' regex='^#[[:space:]]*define[[:space:]]+PERF_EVENT_IOC_(\w+)[[:space:]]+_IO[RW]*[[:space:]]*\([[:space:]]*.\$.[[:space:]]*,[[:space:]]*([[:digit:]]+).*'
......
#!/bin/sh #!/bin/sh
header_dir=$1 [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/
printf "static const char *pkey_alloc_access_rights[] = {\n" printf "static const char *pkey_alloc_access_rights[] = {\n"
regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+PKEY_([[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*' regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+PKEY_([[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*'
......
#!/bin/sh #!/bin/sh
sound_header_dir=$1 [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/
printf "static const char *sndrv_ctl_ioctl_cmds[] = {\n" printf "static const char *sndrv_ctl_ioctl_cmds[] = {\n"
grep "^#define[\t ]\+SNDRV_CTL_IOCTL_" $sound_header_dir/asound.h | \ grep "^#define[\t ]\+SNDRV_CTL_IOCTL_" $header_dir/asound.h | \
sed -r 's/^#define +SNDRV_CTL_IOCTL_([A-Z0-9_]+)[\t ]+_IO[RW]*\( *.U., *(0x[[:xdigit:]]+),?.*/\t[\2] = \"\1\",/g' sed -r 's/^#define +SNDRV_CTL_IOCTL_([A-Z0-9_]+)[\t ]+_IO[RW]*\( *.U., *(0x[[:xdigit:]]+),?.*/\t[\2] = \"\1\",/g'
printf "};\n" printf "};\n"
#!/bin/sh #!/bin/sh
sound_header_dir=$1 [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/
printf "static const char *sndrv_pcm_ioctl_cmds[] = {\n" printf "static const char *sndrv_pcm_ioctl_cmds[] = {\n"
grep "^#define[\t ]\+SNDRV_PCM_IOCTL_" $sound_header_dir/asound.h | \ grep "^#define[\t ]\+SNDRV_PCM_IOCTL_" $header_dir/asound.h | \
sed -r 's/^#define +SNDRV_PCM_IOCTL_([A-Z0-9_]+)[\t ]+_IO[RW]*\( *.A., *(0x[[:xdigit:]]+),?.*/\t[\2] = \"\1\",/g' sed -r 's/^#define +SNDRV_PCM_IOCTL_([A-Z0-9_]+)[\t ]+_IO[RW]*\( *.A., *(0x[[:xdigit:]]+),?.*/\t[\2] = \"\1\",/g'
printf "};\n" printf "};\n"
// SPDX-License-Identifier: GPL-2.0
/*
* trace/beauty/socket.c
*
* Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
*/
#include "trace/beauty/beauty.h"
#include <sys/types.h>
#include <sys/socket.h>
static size_t socket__scnprintf_ipproto(int protocol, char *bf, size_t size)
{
#include "trace/beauty/generated/socket_ipproto_array.c"
static DEFINE_STRARRAY(socket_ipproto);
return strarray__scnprintf(&strarray__socket_ipproto, bf, size, "%d", protocol);
}
size_t syscall_arg__scnprintf_socket_protocol(char *bf, size_t size, struct syscall_arg *arg)
{
int domain = syscall_arg__val(arg, 0);
if (domain == AF_INET || domain == AF_INET6)
return socket__scnprintf_ipproto(arg->val, bf, size);
return syscall_arg__scnprintf_int(bf, size, arg);
}
#!/bin/sh
[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
printf "static const char *socket_ipproto[] = {\n"
regex='^[[:space:]]+IPPROTO_(\w+)[[:space:]]+=[[:space:]]+([[:digit:]]+),.*'
egrep $regex ${header_dir}/in.h | \
sed -r "s/$regex/\2 \1/g" | \
sort | xargs printf "\t[%s] = \"%s\",\n"
printf "};\n"
#!/bin/sh #!/bin/sh
vhost_virtio_header_dir=$1 [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
printf "static const char *vhost_virtio_ioctl_cmds[] = {\n" printf "static const char *vhost_virtio_ioctl_cmds[] = {\n"
regex='^#[[:space:]]*define[[:space:]]+VHOST_(\w+)[[:space:]]+_IOW?\([[:space:]]*VHOST_VIRTIO[[:space:]]*,[[:space:]]*(0x[[:xdigit:]]+).*' regex='^#[[:space:]]*define[[:space:]]+VHOST_(\w+)[[:space:]]+_IOW?\([[:space:]]*VHOST_VIRTIO[[:space:]]*,[[:space:]]*(0x[[:xdigit:]]+).*'
egrep $regex ${vhost_virtio_header_dir}/vhost.h | \ egrep $regex ${header_dir}/vhost.h | \
sed -r "s/$regex/\2 \1/g" | \ sed -r "s/$regex/\2 \1/g" | \
sort | xargs printf "\t[%s] = \"%s\",\n" sort | xargs printf "\t[%s] = \"%s\",\n"
printf "};\n" printf "};\n"
printf "static const char *vhost_virtio_ioctl_read_cmds[] = {\n" printf "static const char *vhost_virtio_ioctl_read_cmds[] = {\n"
regex='^#[[:space:]]*define[[:space:]]+VHOST_(\w+)[[:space:]]+_IOW?R\([[:space:]]*VHOST_VIRTIO[[:space:]]*,[[:space:]]*(0x[[:xdigit:]]+).*' regex='^#[[:space:]]*define[[:space:]]+VHOST_(\w+)[[:space:]]+_IOW?R\([[:space:]]*VHOST_VIRTIO[[:space:]]*,[[:space:]]*(0x[[:xdigit:]]+).*'
egrep $regex ${vhost_virtio_header_dir}/vhost.h | \ egrep $regex ${header_dir}/vhost.h | \
sed -r "s/$regex/\2 \1/g" | \ sed -r "s/$regex/\2 \1/g" | \
sort | xargs printf "\t[%s] = \"%s\",\n" sort | xargs printf "\t[%s] = \"%s\",\n"
printf "};\n" printf "};\n"
...@@ -747,7 +747,9 @@ int bpf__load(struct bpf_object *obj) ...@@ -747,7 +747,9 @@ int bpf__load(struct bpf_object *obj)
err = bpf_object__load(obj); err = bpf_object__load(obj);
if (err) { if (err) {
pr_debug("bpf: load objects failed\n"); char bf[128];
libbpf_strerror(err, bf, sizeof(bf));
pr_debug("bpf: load objects failed: err=%d: (%s)\n", err, bf);
return err; return err;
} }
return 0; return 0;
......
...@@ -23,6 +23,7 @@ struct cs_etm_buffer { ...@@ -23,6 +23,7 @@ struct cs_etm_buffer {
}; };
enum cs_etm_sample_type { enum cs_etm_sample_type {
CS_ETM_EMPTY = 0,
CS_ETM_RANGE = 1 << 0, CS_ETM_RANGE = 1 << 0,
CS_ETM_TRACE_ON = 1 << 1, CS_ETM_TRACE_ON = 1 << 1,
}; };
......
...@@ -494,6 +494,10 @@ static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq) ...@@ -494,6 +494,10 @@ static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq)
static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet) static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
{ {
/* Returns 0 for the CS_ETM_TRACE_ON packet */
if (packet->sample_type == CS_ETM_TRACE_ON)
return 0;
/* /*
* The packet records the execution range with an exclusive end address * The packet records the execution range with an exclusive end address
* *
...@@ -505,6 +509,15 @@ static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet) ...@@ -505,6 +509,15 @@ static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
return packet->end_addr - A64_INSTR_SIZE; return packet->end_addr - A64_INSTR_SIZE;
} }
static inline u64 cs_etm__first_executed_instr(struct cs_etm_packet *packet)
{
/* Returns 0 for the CS_ETM_TRACE_ON packet */
if (packet->sample_type == CS_ETM_TRACE_ON)
return 0;
return packet->start_addr;
}
static inline u64 cs_etm__instr_count(const struct cs_etm_packet *packet) static inline u64 cs_etm__instr_count(const struct cs_etm_packet *packet)
{ {
/* /*
...@@ -546,7 +559,7 @@ static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq) ...@@ -546,7 +559,7 @@ static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq)
be = &bs->entries[etmq->last_branch_pos]; be = &bs->entries[etmq->last_branch_pos];
be->from = cs_etm__last_executed_instr(etmq->prev_packet); be->from = cs_etm__last_executed_instr(etmq->prev_packet);
be->to = etmq->packet->start_addr; be->to = cs_etm__first_executed_instr(etmq->packet);
/* No support for mispredict */ /* No support for mispredict */
be->flags.mispred = 0; be->flags.mispred = 0;
be->flags.predicted = 1; be->flags.predicted = 1;
...@@ -701,7 +714,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq) ...@@ -701,7 +714,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
sample.ip = cs_etm__last_executed_instr(etmq->prev_packet); sample.ip = cs_etm__last_executed_instr(etmq->prev_packet);
sample.pid = etmq->pid; sample.pid = etmq->pid;
sample.tid = etmq->tid; sample.tid = etmq->tid;
sample.addr = etmq->packet->start_addr; sample.addr = cs_etm__first_executed_instr(etmq->packet);
sample.id = etmq->etm->branches_id; sample.id = etmq->etm->branches_id;
sample.stream_id = etmq->etm->branches_id; sample.stream_id = etmq->etm->branches_id;
sample.period = 1; sample.period = 1;
...@@ -897,13 +910,23 @@ static int cs_etm__sample(struct cs_etm_queue *etmq) ...@@ -897,13 +910,23 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
etmq->period_instructions = instrs_over; etmq->period_instructions = instrs_over;
} }
if (etm->sample_branches && if (etm->sample_branches && etmq->prev_packet) {
etmq->prev_packet && bool generate_sample = false;
etmq->prev_packet->sample_type == CS_ETM_RANGE &&
etmq->prev_packet->last_instr_taken_branch) { /* Generate sample for tracing on packet */
ret = cs_etm__synth_branch_sample(etmq); if (etmq->prev_packet->sample_type == CS_ETM_TRACE_ON)
if (ret) generate_sample = true;
return ret;
/* Generate sample for branch taken packet */
if (etmq->prev_packet->sample_type == CS_ETM_RANGE &&
etmq->prev_packet->last_instr_taken_branch)
generate_sample = true;
if (generate_sample) {
ret = cs_etm__synth_branch_sample(etmq);
if (ret)
return ret;
}
} }
if (etm->sample_branches || etm->synth_opts.last_branch) { if (etm->sample_branches || etm->synth_opts.last_branch) {
...@@ -922,10 +945,17 @@ static int cs_etm__sample(struct cs_etm_queue *etmq) ...@@ -922,10 +945,17 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
static int cs_etm__flush(struct cs_etm_queue *etmq) static int cs_etm__flush(struct cs_etm_queue *etmq)
{ {
int err = 0; int err = 0;
struct cs_etm_auxtrace *etm = etmq->etm;
struct cs_etm_packet *tmp; struct cs_etm_packet *tmp;
if (!etmq->prev_packet)
return 0;
/* Handle start tracing packet */
if (etmq->prev_packet->sample_type == CS_ETM_EMPTY)
goto swap_packet;
if (etmq->etm->synth_opts.last_branch && if (etmq->etm->synth_opts.last_branch &&
etmq->prev_packet &&
etmq->prev_packet->sample_type == CS_ETM_RANGE) { etmq->prev_packet->sample_type == CS_ETM_RANGE) {
/* /*
* Generate a last branch event for the branches left in the * Generate a last branch event for the branches left in the
...@@ -944,6 +974,17 @@ static int cs_etm__flush(struct cs_etm_queue *etmq) ...@@ -944,6 +974,17 @@ static int cs_etm__flush(struct cs_etm_queue *etmq)
etmq->period_instructions = 0; etmq->period_instructions = 0;
}
if (etm->sample_branches &&
etmq->prev_packet->sample_type == CS_ETM_RANGE) {
err = cs_etm__synth_branch_sample(etmq);
if (err)
return err;
}
swap_packet:
if (etmq->etm->synth_opts.last_branch) {
/* /*
* Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
* the next incoming packet. * the next incoming packet.
...@@ -1023,6 +1064,13 @@ static int cs_etm__run_decoder(struct cs_etm_queue *etmq) ...@@ -1023,6 +1064,13 @@ static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
*/ */
cs_etm__flush(etmq); cs_etm__flush(etmq);
break; break;
case CS_ETM_EMPTY:
/*
* Should not receive empty packet,
* report error.
*/
pr_err("CS ETM Trace: empty packet\n");
return -EINVAL;
default: default:
break; break;
} }
......
...@@ -859,6 +859,12 @@ static void apply_config_terms(struct perf_evsel *evsel, ...@@ -859,6 +859,12 @@ static void apply_config_terms(struct perf_evsel *evsel,
} }
} }
static bool is_dummy_event(struct perf_evsel *evsel)
{
return (evsel->attr.type == PERF_TYPE_SOFTWARE) &&
(evsel->attr.config == PERF_COUNT_SW_DUMMY);
}
/* /*
* The enable_on_exec/disabled value strategy: * The enable_on_exec/disabled value strategy:
* *
...@@ -1097,6 +1103,14 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts, ...@@ -1097,6 +1103,14 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
else else
perf_evsel__reset_sample_bit(evsel, PERIOD); perf_evsel__reset_sample_bit(evsel, PERIOD);
} }
/*
* For initial_delay, a dummy event is added implicitly.
* The software event will trigger -EOPNOTSUPP error out,
* if BRANCH_STACK bit is set.
*/
if (opts->initial_delay && is_dummy_event(evsel))
perf_evsel__reset_sample_bit(evsel, BRANCH_STACK);
} }
static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
......
...@@ -326,8 +326,8 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, ...@@ -326,8 +326,8 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter,
if (raw) if (raw)
s = (char *)pe->metric_name; s = (char *)pe->metric_name;
else { else {
if (asprintf(&s, "%s\n\t[%s]", if (asprintf(&s, "%s\n%*s%s]",
pe->metric_name, pe->desc) < 0) pe->metric_name, 8, "[", pe->desc) < 0)
return; return;
} }
......
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