summaryrefslogtreecommitdiff
path: root/io_uring.c
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@altlinux.org>2019-05-19 23:35:20 +0000
committerDmitry V. Levin <ldv@altlinux.org>2019-05-19 23:35:20 +0000
commitd7e00d657a1f623d5f794827e4bfe6db1abaad34 (patch)
tree38817572854b0844b05ad3e4787934ccaec26005 /io_uring.c
parentf625d610c7018cef0380f81e513695c66615443c (diff)
downloadstrace-d7e00d657a1f623d5f794827e4bfe6db1abaad34.tar.gz
Implement decoding of io_uring_* syscalls
... introduced by Linux kernel commits v5.1-rc1~99^2~14, v5.1-rc1~99^2~7, and v5.1-rc7~24^2. * configure.ac (AC_CHECK_HEADERS): Add linux/io_uring.h. * io_uring.c: New file. * Makefile.am (strace_SOURCES): Add it. * pathtrace.c (pathtrace_match_set): Add SEN_io_uring_enter, SEN_io_uring_register, and SEN_io_uring_setup. * xlat/uring_enter_flags.in: New file. * xlat/uring_register_opcodes.in: Likewise. * linux/32/syscallent.h [425, 426, 427]: Wire up io_uring_setup, io_uring_enter, and io_uring_register. * linux/64/syscallent.h: Likewise. * linux/arm/syscallent.h: Likewise. * linux/hppa/syscallent.h: Likewise. * linux/i386/syscallent.h: Likewise. * linux/m68k/syscallent.h: Likewise. * linux/microblaze/syscallent.h: Likewise. * linux/powerpc/syscallent.h: Likewise. * linux/powerpc64/syscallent.h: Likewise. * linux/s390/syscallent.h: Likewise. * linux/s390x/syscallent.h: Likewise. * linux/sh/syscallent.h: Likewise. * linux/sh64/syscallent.h: Likewise. * linux/sparc/syscallent.h: Likewise. * linux/sparc64/syscallent.h: Likewise. * linux/x32/syscallent.h: Likewise. * linux/x86_64/syscallent.h: Likewise. * linux/xtensa/syscallent.h: Likewise. * linux/alpha/syscallent.h [535, 536, 537]: Likewise. * linux/ia64/syscallent.h [1024 + 425, 1024 + 426, 1024 + 427]: Likewise. * linux/mips/syscallent-n32.h [6425, 6426, 6427]: Likewise. * linux/mips/syscallent-n64.h [5425, 5426, 5427]: Likewise. * linux/mips/syscallent-o32.h [4425, 4426, 4427]: Likewise. * NEWS: Mention this change. * tests/io_uring_enter.c: New file. * tests/io_uring_register.c: Likewise. * tests/io_uring_setup.c: Likewise. * tests/gen_tests.in (io_uring_enter, io_uring_register, io_uring_setup): New entries. * tests/pure_executables.list: Add io_uring_enter, io_uring_register, and io_uring_setup. * tests/.gitignore: Likewise.
Diffstat (limited to 'io_uring.c')
-rw-r--r--io_uring.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/io_uring.c b/io_uring.c
new file mode 100644
index 000000000..0b82a0754
--- /dev/null
+++ b/io_uring.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2019 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "defs.h"
+
+#ifdef HAVE_LINUX_IO_URING_H
+# include "print_fields.h"
+# include <linux/io_uring.h>
+#endif
+
+#include "xlat/uring_setup_flags.h"
+#include "xlat/uring_enter_flags.h"
+#include "xlat/uring_register_opcodes.h"
+
+SYS_FUNC(io_uring_setup)
+{
+ const uint32_t nentries = tcp->u_arg[0];
+ const kernel_ulong_t params_addr = tcp->u_arg[1];
+
+#ifdef HAVE_LINUX_IO_URING_H
+ struct io_uring_params params;
+
+ if (entering(tcp)) {
+ tprintf("%u, ", nentries);
+
+ if (umove_or_printaddr(tcp, params_addr, &params))
+ return RVAL_DECODED | RVAL_FD;
+
+ PRINT_FIELD_FLAGS("{", params, flags, uring_setup_flags,
+ "IORING_SETUP_???");
+ PRINT_FIELD_X(", ", params, sq_thread_cpu);
+ PRINT_FIELD_U(", ", params, sq_thread_idle);
+ for (unsigned int i = 0; i < ARRAY_SIZE(params.resv); ++i) {
+ if (params.resv[i]) {
+ for (i = 0; i < ARRAY_SIZE(params.resv); ++i)
+ tprintf("%s%#x",
+ (i ? ", " : ", resv={"),
+ params.resv[i]);
+ tprints("}");
+ break;
+ }
+ }
+ return 0;
+ } else {
+ if (syserror(tcp)) {
+ /* The remaining part of params is irrelevant. */
+ } else if (umove(tcp, params_addr, &params)) {
+ tprints(", ???");
+ } else {
+ PRINT_FIELD_U(", ", params, sq_entries);
+ PRINT_FIELD_U(", ", params, cq_entries);
+ PRINT_FIELD_U(", sq_off={", params.sq_off, head);
+ PRINT_FIELD_U(", ", params.sq_off, tail);
+ PRINT_FIELD_U(", ", params.sq_off, ring_mask);
+ PRINT_FIELD_U(", ", params.sq_off, ring_entries);
+ PRINT_FIELD_U(", ", params.sq_off, flags);
+ PRINT_FIELD_U(", ", params.sq_off, dropped);
+ PRINT_FIELD_U(", ", params.sq_off, array);
+ PRINT_FIELD_U("}, cq_off={", params.cq_off, head);
+ PRINT_FIELD_U(", ", params.cq_off, tail);
+ PRINT_FIELD_U(", ", params.cq_off, ring_mask);
+ PRINT_FIELD_U(", ", params.cq_off, ring_entries);
+ PRINT_FIELD_U(", ", params.cq_off, overflow);
+ PRINT_FIELD_U(", ", params.cq_off, cqes);
+ tprints("}");
+ }
+ tprints("}");
+ }
+#else /* !HAVE_LINUX_IO_URING_H */
+ tprintf("%u, ", nentries);
+ printaddr(params_addr);
+#endif
+
+ return RVAL_DECODED | RVAL_FD;
+}
+
+SYS_FUNC(io_uring_enter)
+{
+ const int fd = tcp->u_arg[0];
+ const uint32_t to_submit = tcp->u_arg[1];
+ const uint32_t min_complete = tcp->u_arg[2];
+ const uint32_t flags = tcp->u_arg[3];
+ const kernel_ulong_t sigset_addr = tcp->u_arg[4];
+ const kernel_ulong_t sigset_size = tcp->u_arg[5];
+
+ printfd(tcp, fd);
+ tprintf(", %u, %u, ", to_submit, min_complete);
+ printflags(uring_enter_flags, flags, "IORING_ENTER_???");
+ tprints(", ");
+ print_sigset_addr_len(tcp, sigset_addr, sigset_size);
+ tprintf(", %" PRI_klu, sigset_size);
+
+ return RVAL_DECODED;
+}
+
+static bool
+print_fd_array_member(struct tcb *tcp, void *elem_buf, size_t elem_size,
+ void *data)
+{
+ printfd(tcp, *(int *) elem_buf);
+ return true;
+}
+
+SYS_FUNC(io_uring_register)
+{
+ const int fd = tcp->u_arg[0];
+ const unsigned int opcode = tcp->u_arg[1];
+ const kernel_ulong_t arg = tcp->u_arg[2];
+ const unsigned int nargs = tcp->u_arg[3];
+ int buf;
+
+ printfd(tcp, fd);
+ tprints(", ");
+ printxval(uring_register_opcodes, opcode, "IORING_REGISTER_???");
+ tprints(", ");
+ switch (opcode) {
+ case IORING_REGISTER_BUFFERS:
+ tprint_iov(tcp, nargs, arg, IOV_DECODE_ADDR);
+ break;
+ case IORING_REGISTER_FILES:
+ print_array(tcp, arg, nargs, &buf, sizeof(buf),
+ tfetch_mem, print_fd_array_member, NULL);
+ break;
+ default:
+ printaddr(arg);
+ break;
+ }
+ tprintf(", %u", nargs);
+
+ return RVAL_DECODED;
+}