1 /*
2 * Check decoding of io_uring_setup syscall.
3 *
4 * Copyright (c) 2019 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2019-2023 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12 #include "scno.h"
13
14 #include <fcntl.h>
15 #include <stdio.h>
16 #include <stdint.h>
17 #include <string.h>
18 #include <unistd.h>
19
20 #include "kernel_time_types.h"
21 #define UAPI_LINUX_IO_URING_H_SKIP_LINUX_TIME_TYPES_H
22 #include <linux/io_uring.h>
23
24 #include <sys/stat.h>
25 #include <sys/types.h>
26
27 #include "print_fields.h"
28 #include "xlat.h"
29
30 #include "xlat/uring_setup_features.h"
31
32 static const char *errstr;
33
34 static long
35 sys_io_uring_setup(uint32_t nentries, const void *params)
36 {
37 kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL;
38 kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL;
39 kernel_ulong_t arg1 = fill | nentries;
40 kernel_ulong_t arg2 = (unsigned long) params;
41
42 long rc = syscall(__NR_io_uring_setup, arg1, arg2, bad, bad, bad, bad);
43 errstr = sprintrc(rc);
44 return rc;
45 }
46
47 int
48 main(void)
49 {
50 static const char path_full[] = "/dev/full";
51
52 long rc;
53 TAIL_ALLOC_OBJECT_CONST_PTR(struct io_uring_params, params);
54 const void *efault = (const void *) params + 1;
55
56 skip_if_unavailable("/proc/self/fd/");
57
58 int fd_full = open(path_full, O_RDONLY);
59 if (fd_full < 0)
60 perror_msg_and_fail("open: %s", path_full);
61
62 sys_io_uring_setup(-1U, NULL);
63 printf("io_uring_setup(%u, NULL) = %s\n", -1U, errstr);
64
65 sys_io_uring_setup(0, efault);
66 printf("io_uring_setup(%u, %p) = %s\n", 0, efault, errstr);
67
68 fill_memory(params, sizeof(*params));
69 params->flags = -1;
70 sys_io_uring_setup(1, params);
71 printf("io_uring_setup(%u, {flags=IORING_SETUP_IOPOLL"
72 "|IORING_SETUP_SQPOLL|IORING_SETUP_SQ_AFF|IORING_SETUP_CQSIZE"
73 "|IORING_SETUP_CLAMP|IORING_SETUP_ATTACH_WQ"
74 "|IORING_SETUP_R_DISABLED|IORING_SETUP_SUBMIT_ALL"
75 "|IORING_SETUP_COOP_TASKRUN|IORING_SETUP_TASKRUN_FLAG"
76 "|IORING_SETUP_SQE128|IORING_SETUP_CQE32"
77 "|IORING_SETUP_SINGLE_ISSUER|IORING_SETUP_DEFER_TASKRUN"
78 "|IORING_SETUP_NO_MMAP|IORING_SETUP_REGISTERED_FD_ONLY"
79 "|%#x"
80 ", sq_thread_cpu=%#x, sq_thread_idle=%u, wq_fd=%d, resv=[",
81 1, -1U - 0xffff, params->sq_thread_cpu, params->sq_thread_idle,
82 params->wq_fd);
83 for (unsigned int i = 0; i < ARRAY_SIZE(params->resv); ++i)
84 printf("%s%#x", i != 0 ? ", " : "", params->resv[i]);
85 printf("]}) = %s\n", errstr);
86
87 for (size_t i = 0; i < 2; i++) {
88 memset(params, 0, sizeof(*params));
89
90 params->wq_fd = i == 1 ? fd_full : -1;
91 params->flags = i == 1 ? 32 : 0;
92
93 rc = sys_io_uring_setup(2, params);
94 printf("io_uring_setup(%u, {flags=%s, sq_thread_cpu=0"
95 ", sq_thread_idle=0",
96 2, i == 1 ? "IORING_SETUP_ATTACH_WQ" : "0");
97 if (i == 1)
98 printf(", wq_fd=%d<%s>", fd_full, path_full);
99 if (rc < 0) {
100 printf("}) = %s\n", errstr);
101 } else {
102 printf(", sq_entries=%u, cq_entries=%u, features=",
103 params->sq_entries,
104 params->cq_entries);
105 printflags(uring_setup_features, params->features,
106 "IORING_FEAT_???");
107 printf(", sq_off={head=%u, tail=%u, ring_mask=%u"
108 ", ring_entries=%u, flags=%u, dropped=%u"
109 ", array=%u",
110 params->sq_off.head,
111 params->sq_off.tail,
112 params->sq_off.ring_mask,
113 params->sq_off.ring_entries,
114 params->sq_off.flags,
115 params->sq_off.dropped,
116 params->sq_off.array);
117 if (params->sq_off.resv1)
118 printf(", resv1=%#x", params->sq_off.resv1);
119 printf(", user_addr=%#llx",
120 (unsigned long long)
121 params->sq_off.user_addr);
122
123 printf("}, cq_off={head=%u, tail=%u, ring_mask=%u"
124 ", ring_entries=%u, overflow=%u, cqes=%u"
125 ", flags=%u",
126 params->cq_off.head,
127 params->cq_off.tail,
128 params->cq_off.ring_mask,
129 params->cq_off.ring_entries,
130 params->cq_off.overflow,
131 params->cq_off.cqes,
132 params->cq_off.flags);
133 if (params->cq_off.resv1)
134 printf(", resv1=%#x", params->cq_off.resv1);
135 printf(", user_addr=%#llx",
136 (unsigned long long)
137 params->cq_off.user_addr);
138
139 printf("}}) = %ld<anon_inode:[io_uring]>\n", rc);
140 }
141 }
142
143 puts("+++ exited with 0 +++");
144 return 0;
145 }