summaryrefslogtreecommitdiff
path: root/tools/perf/trace
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/trace')
-rw-r--r--tools/perf/trace/beauty/Build6
-rw-r--r--tools/perf/trace/beauty/beauty.h74
-rw-r--r--tools/perf/trace/beauty/clone.c75
-rwxr-xr-xtools/perf/trace/beauty/drm_ioctl.sh13
-rw-r--r--tools/perf/trace/beauty/fcntl.c100
-rw-r--r--tools/perf/trace/beauty/ioctl.c162
-rwxr-xr-xtools/perf/trace/beauty/kvm_ioctl.sh11
-rw-r--r--tools/perf/trace/beauty/mmap.c3
-rw-r--r--tools/perf/trace/beauty/open_flags.c29
-rwxr-xr-xtools/perf/trace/beauty/perf_ioctl.sh10
-rw-r--r--tools/perf/trace/beauty/pid.c4
-rw-r--r--tools/perf/trace/beauty/pkey_alloc.c50
-rwxr-xr-xtools/perf/trace/beauty/pkey_alloc_access_rights.sh10
-rwxr-xr-xtools/perf/trace/beauty/sndrv_ctl_ioctl.sh8
-rwxr-xr-xtools/perf/trace/beauty/sndrv_pcm_ioctl.sh8
-rwxr-xr-xtools/perf/trace/beauty/vhost_virtio_ioctl.sh17
16 files changed, 569 insertions, 11 deletions
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build
index be95ac6ce845..175d633c6b49 100644
--- a/tools/perf/trace/beauty/Build
+++ b/tools/perf/trace/beauty/Build
@@ -1 +1,7 @@
+libperf-y += clone.o
+libperf-y += fcntl.o
+ifeq ($(SRCARCH),$(filter $(SRCARCH),x86))
+libperf-y += ioctl.o
+endif
+libperf-y += pkey_alloc.o
libperf-y += statx.o
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index cf50be3f17a4..4b58581a6053 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -1,13 +1,44 @@
#ifndef _PERF_TRACE_BEAUTY_H
#define _PERF_TRACE_BEAUTY_H
+#include <linux/kernel.h>
#include <linux/types.h>
+struct strarray {
+ int offset;
+ int nr_entries;
+ const char **entries;
+};
+
+#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
+ .nr_entries = ARRAY_SIZE(array), \
+ .entries = array, \
+}
+
+#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
+ .offset = off, \
+ .nr_entries = ARRAY_SIZE(array), \
+ .entries = array, \
+}
+
+size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val);
+
struct trace;
struct thread;
+/**
+ * @val: value of syscall argument being formatted
+ * @args: All the args, use syscall_args__val(arg, nth) to access one
+ * @thread: tid state (maps, pid, tid, etc)
+ * @trace: 'perf trace' internals: all threads, etc
+ * @parm: private area, may be an strarray, for instance
+ * @idx: syscall arg idx (is this the first?)
+ * @mask: a syscall arg may mask another arg, see syscall_arg__scnprintf_futex_op
+ */
+
struct syscall_arg {
unsigned long val;
+ unsigned char *args;
struct thread *thread;
struct trace *trace;
void *parm;
@@ -15,10 +46,53 @@ struct syscall_arg {
u8 mask;
};
+unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx);
+
+size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_STRARRAYS syscall_arg__scnprintf_strarrays
+
+size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_FD syscall_arg__scnprintf_fd
+
+size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_HEX syscall_arg__scnprintf_hex
+
+size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_INT syscall_arg__scnprintf_int
+
+size_t syscall_arg__scnprintf_long(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_LONG syscall_arg__scnprintf_long
+
+size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_PID syscall_arg__scnprintf_pid
+
+size_t syscall_arg__scnprintf_clone_flags(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_CLONE_FLAGS syscall_arg__scnprintf_clone_flags
+
+size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_FCNTL_CMD syscall_arg__scnprintf_fcntl_cmd
+
+size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_FCNTL_ARG syscall_arg__scnprintf_fcntl_arg
+
+size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_IOCTL_CMD syscall_arg__scnprintf_ioctl_cmd
+
+size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights
+
+size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
+
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
size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_STATX_MASK syscall_arg__scnprintf_statx_mask
+size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size);
+
+void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
+ size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg));
+
#endif /* _PERF_TRACE_BEAUTY_H */
diff --git a/tools/perf/trace/beauty/clone.c b/tools/perf/trace/beauty/clone.c
new file mode 100644
index 000000000000..d64d049ab991
--- /dev/null
+++ b/tools/perf/trace/beauty/clone.c
@@ -0,0 +1,75 @@
+/*
+ * trace/beauty/cone.c
+ *
+ * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+
+#include "trace/beauty/beauty.h"
+#include <linux/kernel.h>
+#include <sys/types.h>
+#include <uapi/linux/sched.h>
+
+static size_t clone__scnprintf_flags(unsigned long flags, char *bf, size_t size)
+{
+ int printed = 0;
+
+#define P_FLAG(n) \
+ if (flags & CLONE_##n) { \
+ printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
+ flags &= ~CLONE_##n; \
+ }
+
+ P_FLAG(VM);
+ P_FLAG(FS);
+ P_FLAG(FILES);
+ P_FLAG(SIGHAND);
+ P_FLAG(PTRACE);
+ P_FLAG(VFORK);
+ P_FLAG(PARENT);
+ P_FLAG(THREAD);
+ P_FLAG(NEWNS);
+ P_FLAG(SYSVSEM);
+ P_FLAG(SETTLS);
+ P_FLAG(PARENT_SETTID);
+ P_FLAG(CHILD_CLEARTID);
+ P_FLAG(DETACHED);
+ P_FLAG(UNTRACED);
+ P_FLAG(CHILD_SETTID);
+ P_FLAG(NEWCGROUP);
+ P_FLAG(NEWUTS);
+ P_FLAG(NEWIPC);
+ P_FLAG(NEWUSER);
+ P_FLAG(NEWPID);
+ P_FLAG(NEWNET);
+ P_FLAG(IO);
+#undef P_FLAG
+
+ if (flags)
+ printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
+
+ return printed;
+}
+
+size_t syscall_arg__scnprintf_clone_flags(char *bf, size_t size, struct syscall_arg *arg)
+{
+ unsigned long flags = arg->val;
+ enum syscall_clone_args {
+ SCC_FLAGS = (1 << 0),
+ SCC_CHILD_STACK = (1 << 1),
+ SCC_PARENT_TIDPTR = (1 << 2),
+ SCC_CHILD_TIDPTR = (1 << 3),
+ SCC_TLS = (1 << 4),
+ };
+ if (!(flags & CLONE_PARENT_SETTID))
+ arg->mask |= SCC_PARENT_TIDPTR;
+
+ if (!(flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)))
+ arg->mask |= SCC_CHILD_TIDPTR;
+
+ if (!(flags & CLONE_SETTLS))
+ arg->mask |= SCC_TLS;
+
+ return clone__scnprintf_flags(flags, bf, size);
+}
diff --git a/tools/perf/trace/beauty/drm_ioctl.sh b/tools/perf/trace/beauty/drm_ioctl.sh
new file mode 100755
index 000000000000..2149d3a98e42
--- /dev/null
+++ b/tools/perf/trace/beauty/drm_ioctl.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+drm_header_dir=$1
+printf "#ifndef DRM_COMMAND_BASE\n"
+grep "#define DRM_COMMAND_BASE" $drm_header_dir/drm.h
+printf "#endif\n"
+
+printf "static const char *drm_ioctl_cmds[] = {\n"
+grep "^#define DRM_IOCTL.*DRM_IO" $drm_header_dir/drm.h | \
+ 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 | \
+ sed -r 's/^#define +DRM_I915_([A-Z0-9_]+)[ ]+(0x[[:xdigit:]]+)/\t[DRM_COMMAND_BASE + \2] = "I915_\1",/g'
+printf "};\n"
diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
new file mode 100644
index 000000000000..9e8900c13cb1
--- /dev/null
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -0,0 +1,100 @@
+/*
+ * trace/beauty/fcntl.c
+ *
+ * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+
+#include "trace/beauty/beauty.h"
+#include <linux/kernel.h>
+#include <uapi/linux/fcntl.h>
+
+static size_t fcntl__scnprintf_getfd(unsigned long val, char *bf, size_t size)
+{
+ return scnprintf(bf, size, "%s", val ? "CLOEXEC" : "0");
+}
+
+static size_t syscall_arg__scnprintf_fcntl_getfd(char *bf, size_t size, struct syscall_arg *arg)
+{
+ return fcntl__scnprintf_getfd(arg->val, bf, size);
+}
+
+static size_t fcntl__scnprintf_getlease(unsigned long val, char *bf, size_t size)
+{
+ static const char *fcntl_setlease[] = { "RDLCK", "WRLCK", "UNLCK", };
+ static DEFINE_STRARRAY(fcntl_setlease);
+
+ return strarray__scnprintf(&strarray__fcntl_setlease, bf, size, "%x", val);
+}
+
+static size_t syscall_arg__scnprintf_fcntl_getlease(char *bf, size_t size, struct syscall_arg *arg)
+{
+ return fcntl__scnprintf_getlease(arg->val, bf, size);
+}
+
+size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg)
+{
+ if (arg->val == F_GETFL) {
+ syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_open_flags);
+ goto mask_arg;
+ }
+ if (arg->val == F_GETFD) {
+ syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fcntl_getfd);
+ goto mask_arg;
+ }
+ if (arg->val == F_DUPFD_CLOEXEC || arg->val == F_DUPFD) {
+ syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fd);
+ goto out;
+ }
+ if (arg->val == F_GETOWN) {
+ syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_pid);
+ goto mask_arg;
+ }
+ if (arg->val == F_GETLEASE) {
+ syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fcntl_getlease);
+ goto mask_arg;
+ }
+ /*
+ * Some commands ignore the third fcntl argument, "arg", so mask it
+ */
+ if (arg->val == F_GET_SEALS ||
+ arg->val == F_GETSIG) {
+mask_arg:
+ arg->mask |= (1 << 2);
+ }
+out:
+ return syscall_arg__scnprintf_strarrays(bf, size, arg);
+}
+
+size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_arg *arg)
+{
+ int cmd = syscall_arg__val(arg, 1);
+
+ if (cmd == F_DUPFD)
+ return syscall_arg__scnprintf_fd(bf, size, arg);
+
+ if (cmd == F_SETFD)
+ return fcntl__scnprintf_getfd(arg->val, bf, size);
+
+ if (cmd == F_SETFL)
+ return open__scnprintf_flags(arg->val, bf, size);
+
+ if (cmd == F_SETOWN)
+ return syscall_arg__scnprintf_pid(bf, size, arg);
+
+ if (cmd == F_SETLEASE)
+ return fcntl__scnprintf_getlease(arg->val, bf, size);
+ /*
+ * We still don't grab the contents of pointers on entry or exit,
+ * so just print them as hex numbers
+ */
+ if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK ||
+ cmd == F_OFD_SETLK || cmd == F_OFD_SETLKW || cmd == F_OFD_GETLK ||
+ cmd == F_GETOWN_EX || cmd == F_SETOWN_EX ||
+ cmd == F_GET_RW_HINT || cmd == F_SET_RW_HINT ||
+ cmd == F_GET_FILE_RW_HINT || cmd == F_SET_FILE_RW_HINT)
+ return syscall_arg__scnprintf_hex(bf, size, arg);
+
+ return syscall_arg__scnprintf_long(bf, size, arg);
+}
diff --git a/tools/perf/trace/beauty/ioctl.c b/tools/perf/trace/beauty/ioctl.c
new file mode 100644
index 000000000000..1be3b4cf0827
--- /dev/null
+++ b/tools/perf/trace/beauty/ioctl.c
@@ -0,0 +1,162 @@
+/*
+ * trace/beauty/ioctl.c
+ *
+ * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+
+#include "trace/beauty/beauty.h"
+#include <linux/kernel.h>
+
+/*
+ * FIXME: to support all arches we have to improve this, for
+ * now, to build on older systems without things like TIOCGEXCL,
+ * get it directly from our copy.
+ *
+ * Right now only x86 is being supported for beautifying ioctl args
+ * in 'perf trace', see tools/perf/trace/beauty/Build and builtin-trace.c
+ */
+#include <uapi/asm-generic/ioctls.h>
+
+static size_t ioctl__scnprintf_tty_cmd(int nr, int dir, char *bf, size_t size)
+{
+ static const char *ioctl_tty_cmd[] = {
+ "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
+ "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL", "TIOCSCTTY",
+ "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI", "TIOCGWINSZ", "TIOCSWINSZ",
+ "TIOCMGET", "TIOCMBIS", "TIOCMBIC", "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR",
+ "FIONREAD", "TIOCLINUX", "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT",
+ "FIONBIO", "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP",
+ [_IOC_NR(TIOCSBRK)] = "TIOCSBRK", "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2",
+ "TCSETSW2", "TCSETSF2", "TIOCGRS48", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
+ "TIOCGDEV", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG", "TIOCVHANGUP", "TIOCGPKT",
+ "TIOCGPTLCK", [_IOC_NR(TIOCGEXCL)] = "TIOCGEXCL", "TIOCGPTPEER",
+ [_IOC_NR(FIONCLEX)] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
+ "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
+ "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
+ "TIOCMIWAIT", "TIOCGICOUNT", };
+ static DEFINE_STRARRAY(ioctl_tty_cmd);
+
+ if (nr < strarray__ioctl_tty_cmd.nr_entries && strarray__ioctl_tty_cmd.entries[nr] != NULL)
+ return scnprintf(bf, size, "%s", strarray__ioctl_tty_cmd.entries[nr]);
+
+ return scnprintf(bf, size, "(%#x, %#x, %#x)", 'T', nr, dir);
+}
+
+static size_t ioctl__scnprintf_drm_cmd(int nr, int dir, char *bf, size_t size)
+{
+#include "trace/beauty/generated/ioctl/drm_ioctl_array.c"
+ static DEFINE_STRARRAY(drm_ioctl_cmds);
+
+ if (nr < strarray__drm_ioctl_cmds.nr_entries && strarray__drm_ioctl_cmds.entries[nr] != NULL)
+ return scnprintf(bf, size, "DRM_%s", strarray__drm_ioctl_cmds.entries[nr]);
+
+ return scnprintf(bf, size, "(%#x, %#x, %#x)", 'd', nr, dir);
+}
+
+static size_t ioctl__scnprintf_sndrv_pcm_cmd(int nr, int dir, char *bf, size_t size)
+{
+#include "trace/beauty/generated/ioctl/sndrv_pcm_ioctl_array.c"
+ static DEFINE_STRARRAY(sndrv_pcm_ioctl_cmds);
+
+ if (nr < strarray__sndrv_pcm_ioctl_cmds.nr_entries && strarray__sndrv_pcm_ioctl_cmds.entries[nr] != NULL)
+ return scnprintf(bf, size, "SNDRV_PCM_%s", strarray__sndrv_pcm_ioctl_cmds.entries[nr]);
+
+ return scnprintf(bf, size, "(%#x, %#x, %#x)", 'A', nr, dir);
+}
+
+static size_t ioctl__scnprintf_sndrv_ctl_cmd(int nr, int dir, char *bf, size_t size)
+{
+#include "trace/beauty/generated/ioctl/sndrv_ctl_ioctl_array.c"
+ static DEFINE_STRARRAY(sndrv_ctl_ioctl_cmds);
+
+ if (nr < strarray__sndrv_ctl_ioctl_cmds.nr_entries && strarray__sndrv_ctl_ioctl_cmds.entries[nr] != NULL)
+ return scnprintf(bf, size, "SNDRV_CTL_%s", strarray__sndrv_ctl_ioctl_cmds.entries[nr]);
+
+ return scnprintf(bf, size, "(%#x, %#x, %#x)", 'U', nr, dir);
+}
+
+static size_t ioctl__scnprintf_kvm_cmd(int nr, int dir, char *bf, size_t size)
+{
+#include "trace/beauty/generated/ioctl/kvm_ioctl_array.c"
+ static DEFINE_STRARRAY(kvm_ioctl_cmds);
+
+ if (nr < strarray__kvm_ioctl_cmds.nr_entries && strarray__kvm_ioctl_cmds.entries[nr] != NULL)
+ return scnprintf(bf, size, "KVM_%s", strarray__kvm_ioctl_cmds.entries[nr]);
+
+ return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir);
+}
+
+static size_t ioctl__scnprintf_vhost_virtio_cmd(int nr, int dir, char *bf, size_t size)
+{
+#include "trace/beauty/generated/ioctl/vhost_virtio_ioctl_array.c"
+ static DEFINE_STRARRAY(vhost_virtio_ioctl_cmds);
+ static DEFINE_STRARRAY(vhost_virtio_ioctl_read_cmds);
+ struct strarray *s = (dir & _IOC_READ) ? &strarray__vhost_virtio_ioctl_read_cmds : &strarray__vhost_virtio_ioctl_cmds;
+
+ if (nr < s->nr_entries && s->entries[nr] != NULL)
+ return scnprintf(bf, size, "VHOST_%s", s->entries[nr]);
+
+ return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAF, nr, dir);
+}
+
+static size_t ioctl__scnprintf_perf_cmd(int nr, int dir, char *bf, size_t size)
+{
+#include "trace/beauty/generated/ioctl/perf_ioctl_array.c"
+ static DEFINE_STRARRAY(perf_ioctl_cmds);
+
+ if (nr < strarray__perf_ioctl_cmds.nr_entries && strarray__perf_ioctl_cmds.entries[nr] != NULL)
+ return scnprintf(bf, size, "PERF_%s", strarray__perf_ioctl_cmds.entries[nr]);
+
+ return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir);
+}
+
+static size_t ioctl__scnprintf_cmd(unsigned long cmd, char *bf, size_t size)
+{
+ int dir = _IOC_DIR(cmd),
+ type = _IOC_TYPE(cmd),
+ nr = _IOC_NR(cmd),
+ sz = _IOC_SIZE(cmd);
+ int printed = 0;
+ static const struct ioctl_type {
+ int type;
+ size_t (*scnprintf)(int nr, int dir, char *bf, size_t size);
+ } ioctl_types[] = { /* Must be ordered by type */
+ { .type = '$', .scnprintf = ioctl__scnprintf_perf_cmd, },
+ ['A' - '$'] = { .type = 'A', .scnprintf = ioctl__scnprintf_sndrv_pcm_cmd, },
+ ['T' - '$'] = { .type = 'T', .scnprintf = ioctl__scnprintf_tty_cmd, },
+ ['U' - '$'] = { .type = 'U', .scnprintf = ioctl__scnprintf_sndrv_ctl_cmd, },
+ ['d' - '$'] = { .type = 'd', .scnprintf = ioctl__scnprintf_drm_cmd, },
+ [0xAE - '$'] = { .type = 0xAE, .scnprintf = ioctl__scnprintf_kvm_cmd, },
+ [0xAF - '$'] = { .type = 0xAF, .scnprintf = ioctl__scnprintf_vhost_virtio_cmd, },
+ };
+ const int nr_types = ARRAY_SIZE(ioctl_types);
+
+ if (type >= ioctl_types[0].type && type <= ioctl_types[nr_types - 1].type) {
+ const int index = type - ioctl_types[0].type;
+
+ if (ioctl_types[index].scnprintf != NULL)
+ return ioctl_types[index].scnprintf(nr, dir, bf, size);
+ }
+
+ printed += scnprintf(bf + printed, size - printed, "%c", '(');
+
+ if (dir == _IOC_NONE) {
+ printed += scnprintf(bf + printed, size - printed, "%s", "NONE");
+ } else {
+ if (dir & _IOC_READ)
+ printed += scnprintf(bf + printed, size - printed, "%s", "READ");
+ if (dir & _IOC_WRITE)
+ printed += scnprintf(bf + printed, size - printed, "%s%s", dir & _IOC_READ ? "|" : "", "WRITE");
+ }
+
+ return printed + scnprintf(bf + printed, size - printed, ", %#x, %#x, %#x)", type, nr, sz);
+}
+
+size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg)
+{
+ unsigned long cmd = arg->val;
+
+ return ioctl__scnprintf_cmd(cmd, bf, size);
+}
diff --git a/tools/perf/trace/beauty/kvm_ioctl.sh b/tools/perf/trace/beauty/kvm_ioctl.sh
new file mode 100755
index 000000000000..bd28817afced
--- /dev/null
+++ b/tools/perf/trace/beauty/kvm_ioctl.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+kvm_header_dir=$1
+
+printf "static const char *kvm_ioctl_cmds[] = {\n"
+regex='^#[[:space:]]*define[[:space:]]+KVM_(\w+)[[:space:]]+_IO[RW]*\([[:space:]]*KVMIO[[:space:]]*,[[:space:]]*(0x[[:xdigit:]]+).*'
+egrep $regex ${kvm_header_dir}/kvm.h | \
+ sed -r "s/$regex/\2 \1/g" | \
+ egrep -v " ((ARM|PPC|S390)_|[GS]ET_(DEBUGREGS|PIT2|XSAVE|TSC_KHZ)|CREATE_SPAPR_TCE_64)" | \
+ sort | xargs printf "\t[%s] = \"%s\",\n"
+printf "};\n"
diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c
index af1cfde6b97b..754558f9009d 100644
--- a/tools/perf/trace/beauty/mmap.c
+++ b/tools/perf/trace/beauty/mmap.c
@@ -34,6 +34,9 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
{
int printed = 0, flags = arg->val;
+ if (flags & MAP_ANONYMOUS)
+ arg->mask |= (1 << 4) | (1 << 5); /* Mask 4th ('fd') and 5th ('offset') args, ignored */
+
#define P_MMAP_FLAG(n) \
if (flags & MAP_##n) { \
printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
index f55a4597fc38..e359e041dc0e 100644
--- a/tools/perf/trace/beauty/open_flags.c
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -14,13 +14,16 @@
#define O_NOATIME 01000000
#endif
-static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
- struct syscall_arg *arg)
-{
- int printed = 0, flags = arg->val;
+#ifndef O_TMPFILE
+#define O_TMPFILE 020000000
+#endif
- if (!(flags & O_CREAT))
- arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
+#undef O_LARGEFILE
+#define O_LARGEFILE 00100000
+
+size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size)
+{
+ int printed = 0;
if (flags == 0)
return scnprintf(bf, size, "RDONLY");
@@ -30,6 +33,7 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
flags &= ~O_##n; \
}
+ P_FLAG(RDWR);
P_FLAG(APPEND);
P_FLAG(ASYNC);
P_FLAG(CLOEXEC);
@@ -38,6 +42,8 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
P_FLAG(DIRECTORY);
P_FLAG(EXCL);
P_FLAG(LARGEFILE);
+ P_FLAG(NOFOLLOW);
+ P_FLAG(TMPFILE);
P_FLAG(NOATIME);
P_FLAG(NOCTTY);
#ifdef O_NONBLOCK
@@ -48,7 +54,6 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
#ifdef O_PATH
P_FLAG(PATH);
#endif
- P_FLAG(RDWR);
#ifdef O_DSYNC
if ((flags & O_SYNC) == O_SYNC)
printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
@@ -68,4 +73,12 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
return printed;
}
-#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
+size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg)
+{
+ int flags = arg->val;
+
+ if (!(flags & O_CREAT))
+ arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
+
+ return open__scnprintf_flags(flags, bf, size);
+}
diff --git a/tools/perf/trace/beauty/perf_ioctl.sh b/tools/perf/trace/beauty/perf_ioctl.sh
new file mode 100755
index 000000000000..faea4237c793
--- /dev/null
+++ b/tools/perf/trace/beauty/perf_ioctl.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+header_dir=$1
+
+printf "static const char *perf_ioctl_cmds[] = {\n"
+regex='^#[[:space:]]*define[[:space:]]+PERF_EVENT_IOC_(\w+)[[:space:]]+_IO[RW]*[[:space:]]*\([[:space:]]*.\$.[[:space:]]*,[[:space:]]*([[:digit:]]+).*'
+egrep $regex ${header_dir}/perf_event.h | \
+ sed -r "s/$regex/\2 \1/g" | \
+ sort | xargs printf "\t[%s] = \"%s\",\n"
+printf "};\n"
diff --git a/tools/perf/trace/beauty/pid.c b/tools/perf/trace/beauty/pid.c
index 07486ea65ae3..b6d419e16dcf 100644
--- a/tools/perf/trace/beauty/pid.c
+++ b/tools/perf/trace/beauty/pid.c
@@ -1,4 +1,4 @@
-static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
+size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
{
int pid = arg->val;
struct trace *trace = arg->trace;
@@ -17,5 +17,3 @@ static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_a
return printed;
}
-
-#define SCA_PID syscall_arg__scnprintf_pid
diff --git a/tools/perf/trace/beauty/pkey_alloc.c b/tools/perf/trace/beauty/pkey_alloc.c
new file mode 100644
index 000000000000..2ba784a3734a
--- /dev/null
+++ b/tools/perf/trace/beauty/pkey_alloc.c
@@ -0,0 +1,50 @@
+/*
+ * trace/beauty/pkey_alloc.c
+ *
+ * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+
+#include "trace/beauty/beauty.h"
+#include <linux/kernel.h>
+#include <linux/log2.h>
+
+static size_t pkey_alloc__scnprintf_access_rights(int access_rights, char *bf, size_t size)
+{
+ int i, printed = 0;
+
+#include "trace/beauty/generated/pkey_alloc_access_rights_array.c"
+ static DEFINE_STRARRAY(pkey_alloc_access_rights);
+
+ if (access_rights == 0) {
+ const char *s = strarray__pkey_alloc_access_rights.entries[0];
+ if (s)
+ return scnprintf(bf, size, "%s", s);
+ return scnprintf(bf, size, "%d", 0);
+ }
+
+ for (i = 1; i < strarray__pkey_alloc_access_rights.nr_entries; ++i) {
+ int bit = 1 << (i - 1);
+
+ if (!(access_rights & bit))
+ continue;
+
+ if (printed != 0)
+ printed += scnprintf(bf + printed, size - printed, "|");
+
+ if (strarray__pkey_alloc_access_rights.entries[i] != NULL)
+ printed += scnprintf(bf + printed, size - printed, "%s", strarray__pkey_alloc_access_rights.entries[i]);
+ else
+ printed += scnprintf(bf + printed, size - printed, "0x%#", bit);
+ }
+
+ return printed;
+}
+
+size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg)
+{
+ unsigned long cmd = arg->val;
+
+ return pkey_alloc__scnprintf_access_rights(cmd, bf, size);
+}
diff --git a/tools/perf/trace/beauty/pkey_alloc_access_rights.sh b/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
new file mode 100755
index 000000000000..62e51a02b839
--- /dev/null
+++ b/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+header_dir=$1
+
+printf "static const char *pkey_alloc_access_rights[] = {\n"
+regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+PKEY_([[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*'
+egrep $regex ${header_dir}/mman-common.h | \
+ sed -r "s/$regex/\2 \2 \1/g" | \
+ sort | xargs printf "\t[%s ? (ilog2(%s) + 1) : 0] = \"%s\",\n"
+printf "};\n"
diff --git a/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh b/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh
new file mode 100755
index 000000000000..aad5ab130539
--- /dev/null
+++ b/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+sound_header_dir=$1
+
+printf "static const char *sndrv_ctl_ioctl_cmds[] = {\n"
+grep "^#define[\t ]\+SNDRV_CTL_IOCTL_" $sound_header_dir/asound.h | \
+ sed -r 's/^#define +SNDRV_CTL_IOCTL_([A-Z0-9_]+)[\t ]+_IO[RW]*\( *.U., *(0x[[:xdigit:]]+),?.*/\t[\2] = \"\1\",/g'
+printf "};\n"
diff --git a/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh b/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
new file mode 100755
index 000000000000..b7e9ef6b2f55
--- /dev/null
+++ b/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+sound_header_dir=$1
+
+printf "static const char *sndrv_pcm_ioctl_cmds[] = {\n"
+grep "^#define[\t ]\+SNDRV_PCM_IOCTL_" $sound_header_dir/asound.h | \
+ sed -r 's/^#define +SNDRV_PCM_IOCTL_([A-Z0-9_]+)[\t ]+_IO[RW]*\( *.A., *(0x[[:xdigit:]]+),?.*/\t[\2] = \"\1\",/g'
+printf "};\n"
diff --git a/tools/perf/trace/beauty/vhost_virtio_ioctl.sh b/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
new file mode 100755
index 000000000000..76f1de697787
--- /dev/null
+++ b/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+vhost_virtio_header_dir=$1
+
+printf "static const char *vhost_virtio_ioctl_cmds[] = {\n"
+regex='^#[[:space:]]*define[[:space:]]+VHOST_(\w+)[[:space:]]+_IOW?\([[:space:]]*VHOST_VIRTIO[[:space:]]*,[[:space:]]*(0x[[:xdigit:]]+).*'
+egrep $regex ${vhost_virtio_header_dir}/vhost.h | \
+ sed -r "s/$regex/\2 \1/g" | \
+ sort | xargs printf "\t[%s] = \"%s\",\n"
+printf "};\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:]]+).*'
+egrep $regex ${vhost_virtio_header_dir}/vhost.h | \
+ sed -r "s/$regex/\2 \1/g" | \
+ sort | xargs printf "\t[%s] = \"%s\",\n"
+printf "};\n"