blob: 894cc7be94252b3dc7f7240f409fdd1f89c83851 [file] [log] [blame]
Dezhi Kong288546e2019-05-16 17:02:38 +08001/*
2 * Copyright 2013 Google, Inc
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <errno.h>
18#include <fcntl.h>
19#include <getopt.h>
20#include <string.h>
21#include <stdlib.h>
22#include <stdio.h>
23#include <sys/mman.h>
24#include <sys/ioctl.h>
25#include <sys/socket.h>
26#include <sys/stat.h>
27#include <sys/types.h>
28#include <unistd.h>
29
30#include <ion/ion.h>
Dezhi Kong528d8cc2019-07-17 21:09:07 +080031#include <ion/IONmem.h>
Dezhi Kong288546e2019-05-16 17:02:38 +080032#include <linux/ion.h>
33
34size_t len = 1024*1024, align = 0;
35int prot = PROT_READ | PROT_WRITE;
36int map_flags = MAP_SHARED;
37int alloc_flags = 0;
38int heap_mask = 1;
39int test = -1;
40size_t stride;
41
Cao Jian510569c2019-08-16 14:01:44 +080042int _ionmem_alloc_test(void)
Dezhi Kong528d8cc2019-07-17 21:09:07 +080043{
Cao Jian510569c2019-08-16 14:01:44 +080044 int ret, ion_fd = -1;
Dezhi Kong528d8cc2019-07-17 21:09:07 +080045 IONMEM_AllocParams params;
46
Cao Jian510569c2019-08-16 14:01:44 +080047 ion_fd = ion_mem_init();
48 if (ion_fd < 0) {
49 printf("ion_mem_init failed\n");
50 return ion_fd;
Yongjie Zhu7f547df2022-01-11 15:35:19 +080051 } else {
52 ret = ion_mem_alloc(ion_fd, len, &params, alloc_flags);
53 ion_close(ion_fd);
54 if (ret)
55 printf("%s failed: %s\n", __func__, strerror(ret));
56 else
57 printf("%s: passed\n", __func__);
58 return ret;
Cao Jian510569c2019-08-16 14:01:44 +080059 }
Dezhi Kong528d8cc2019-07-17 21:09:07 +080060}
61
Yongjie Zhu7f547df2022-01-11 15:35:19 +080062int _ion_alloc_test(int fd, ion_user_handle_t *handle)
Dezhi Kong288546e2019-05-16 17:02:38 +080063{
64 int ret;
Dezhi Kong528d8cc2019-07-17 21:09:07 +080065 int legacy_ion = 0;
Dezhi Kong288546e2019-05-16 17:02:38 +080066
Yongjie Zhu7f547df2022-01-11 15:35:19 +080067 fd = ion_open();
68 if (fd < 0)
69 return fd;
Dezhi Kong288546e2019-05-16 17:02:38 +080070
Yongjie Zhu7f547df2022-01-11 15:35:19 +080071 legacy_ion = ion_is_legacy(fd);
Dezhi Kong528d8cc2019-07-17 21:09:07 +080072 printf("legacy_ion=%d\n", legacy_ion);
73 if (legacy_ion)
Yongjie Zhu7f547df2022-01-11 15:35:19 +080074 ret = ion_alloc(fd, len, align, heap_mask, alloc_flags, handle);
Dezhi Kong528d8cc2019-07-17 21:09:07 +080075 else
Yongjie Zhu7f547df2022-01-11 15:35:19 +080076 ret = ion_alloc_fd(fd, len, align, heap_mask, alloc_flags, handle);
Dezhi Kong288546e2019-05-16 17:02:38 +080077
Yongjie Zhu7f547df2022-01-11 15:35:19 +080078 ion_close(fd);
79 if (ret < 0)
80 printf("failed alloc dma buffer\n");
Dezhi Kong288546e2019-05-16 17:02:38 +080081 return ret;
82}
83
84void ion_alloc_test()
85{
Yongjie Zhu7f547df2022-01-11 15:35:19 +080086 int fd = 0;
87 int ret = 0;
Dezhi Kong288546e2019-05-16 17:02:38 +080088 ion_user_handle_t handle;
89
Yongjie Zhu7f547df2022-01-11 15:35:19 +080090 if (_ion_alloc_test(fd, &handle))
Dezhi Kong288546e2019-05-16 17:02:38 +080091 return;
92
Dezhi Kong528d8cc2019-07-17 21:09:07 +080093 if (ion_is_legacy(fd))
94 ret = ion_free(fd, handle);
Dezhi Kong288546e2019-05-16 17:02:38 +080095 if (ret) {
96 printf("%s failed: %s %d\n", __func__, strerror(ret), handle);
97 return;
98 }
Yongjie Zhu7f547df2022-01-11 15:35:19 +080099
Dezhi Kong288546e2019-05-16 17:02:38 +0800100 ion_close(fd);
101 printf("ion alloc test: passed\n");
102}
103
104void ion_map_test()
105{
Yongjie Zhu7f547df2022-01-11 15:35:19 +0800106 int fd = 0;
107 int map_fd, ret;
Dezhi Kong288546e2019-05-16 17:02:38 +0800108 size_t i;
109 ion_user_handle_t handle;
110 unsigned char *ptr;
111
Yongjie Zhu7f547df2022-01-11 15:35:19 +0800112 if (_ion_alloc_test(fd, &handle))
Dezhi Kong288546e2019-05-16 17:02:38 +0800113 return;
114
115 ret = ion_map(fd, handle, len, prot, map_flags, 0, &ptr, &map_fd);
Yongjie Zhu7f547df2022-01-11 15:35:19 +0800116 if (ret) {
117 munmap(ptr, len);
Dezhi Kong288546e2019-05-16 17:02:38 +0800118 return;
Yongjie Zhu7f547df2022-01-11 15:35:19 +0800119 }
Dezhi Kong288546e2019-05-16 17:02:38 +0800120
121 for (i = 0; i < len; i++) {
122 ptr[i] = (unsigned char)i;
123 }
124 for (i = 0; i < len; i++)
125 if (ptr[i] != (unsigned char)i)
126 printf("%s failed wrote %zu read %d from mapped "
127 "memory\n", __func__, i, ptr[i]);
128 /* clean up properly */
129 ret = ion_free(fd, handle);
130 ion_close(fd);
131 munmap(ptr, len);
132 close(map_fd);
133
Dezhi Kong288546e2019-05-16 17:02:38 +0800134#if 0
135 munmap(ptr, len);
136 close(map_fd);
137 ion_close(fd);
138
139 _ion_alloc_test(len, align, flags, &fd, &handle);
140 close(map_fd);
141 ret = ion_map(fd, handle, len, prot, flags, 0, &ptr, &map_fd);
142 /* don't clean up */
143#endif
144}
145
146void ion_share_test()
147
148{
149 ion_user_handle_t handle;
150 int sd[2];
151 int num_fd = 1;
152 struct iovec count_vec = {
153 .iov_base = &num_fd,
154 .iov_len = sizeof num_fd,
155 };
156 char buf[CMSG_SPACE(sizeof(int))];
157 socketpair(AF_UNIX, SOCK_STREAM, 0, sd);
158 if (fork()) {
159 struct msghdr msg = {
160 .msg_control = buf,
161 .msg_controllen = sizeof buf,
162 .msg_iov = &count_vec,
163 .msg_iovlen = 1,
164 };
165
166 struct cmsghdr *cmsg;
Yongjie Zhu7f547df2022-01-11 15:35:19 +0800167 int fd = 0;
168 int share_fd, ret;
Dezhi Kong288546e2019-05-16 17:02:38 +0800169 char *ptr;
170 /* parent */
Yongjie Zhu7f547df2022-01-11 15:35:19 +0800171 if (_ion_alloc_test(fd, &handle))
Dezhi Kong288546e2019-05-16 17:02:38 +0800172 return;
173 ret = ion_share(fd, handle, &share_fd);
174 if (ret)
175 printf("share failed %s\n", strerror(errno));
176 ptr = mmap(NULL, len, prot, map_flags, share_fd, 0);
177 if (ptr == MAP_FAILED) {
Yongjie Zhu7f547df2022-01-11 15:35:19 +0800178 close(fd);
Dezhi Kong288546e2019-05-16 17:02:38 +0800179 return;
180 }
181 strcpy(ptr, "master");
182 cmsg = CMSG_FIRSTHDR(&msg);
183 cmsg->cmsg_level = SOL_SOCKET;
184 cmsg->cmsg_type = SCM_RIGHTS;
185 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
186 *(int *)CMSG_DATA(cmsg) = share_fd;
187 /* send the fd */
188 printf("master? [%10s] should be [master]\n", ptr);
189 printf("master sending msg 1\n");
Yongjie Zhu7f547df2022-01-11 15:35:19 +0800190 if (sendmsg(sd[0], &msg, 0) < 0)
191 perror("master send msg 2");
Dezhi Kong288546e2019-05-16 17:02:38 +0800192 if (recvmsg(sd[0], &msg, 0) < 0)
193 perror("master recv msg 2");
194 printf("master? [%10s] should be [child]\n", ptr);
195
196 /* send ping */
Yongjie Zhu7f547df2022-01-11 15:35:19 +0800197 if (sendmsg(sd[0], &msg, 0) < 0)
198 perror("master send msg 1");
Dezhi Kong288546e2019-05-16 17:02:38 +0800199 printf("master->master? [%10s]\n", ptr);
200 if (recvmsg(sd[0], &msg, 0) < 0)
201 perror("master recv 1");
202 close(fd);
203 _exit(0);
204 } else {
205 struct cmsghdr *cmsg;
206 char* ptr;
207 int fd, recv_fd;
208 char* child_buf[100];
209 /* child */
210 struct iovec count_vec = {
211 .iov_base = child_buf,
212 .iov_len = sizeof child_buf,
213 };
214
215 struct msghdr child_msg = {
216 .msg_control = buf,
217 .msg_controllen = sizeof buf,
218 .msg_iov = &count_vec,
219 .msg_iovlen = 1,
220 };
221
222 if (recvmsg(sd[1], &child_msg, 0) < 0)
223 perror("child recv msg 1");
224 cmsg = CMSG_FIRSTHDR(&child_msg);
225 if (cmsg == NULL) {
226 printf("no cmsg rcvd in child");
227 return;
228 }
229 recv_fd = *(int*)CMSG_DATA(cmsg);
230 if (recv_fd < 0) {
231 printf("could not get recv_fd from socket");
232 return;
233 }
234 printf("child %d\n", recv_fd);
235 fd = ion_open();
Yongjie Zhu7f547df2022-01-11 15:35:19 +0800236 if (fd < 0)
237 return fd;
Dezhi Kong288546e2019-05-16 17:02:38 +0800238 ptr = mmap(NULL, len, prot, map_flags, recv_fd, 0);
239 if (ptr == MAP_FAILED) {
Yongjie Zhu7f547df2022-01-11 15:35:19 +0800240 close(fd);
Dezhi Kong288546e2019-05-16 17:02:38 +0800241 return;
242 }
243 printf("child? [%10s] should be [master]\n", ptr);
244 strcpy(ptr, "child");
245 printf("child sending msg 2\n");
Yongjie Zhu7f547df2022-01-11 15:35:19 +0800246 if (sendmsg(sd[1], &child_msg, 0) < 0)
247 perror("master send msg 2");
Dezhi Kong288546e2019-05-16 17:02:38 +0800248 close(fd);
Yongjie Zhu7f547df2022-01-11 15:35:19 +0800249 _exit(0);
Dezhi Kong288546e2019-05-16 17:02:38 +0800250 }
251}
252
253int main(int argc, char* argv[]) {
254 int c;
255 enum tests {
Cao Jian510569c2019-08-16 14:01:44 +0800256 ALLOC_TEST = 0, MAP_TEST, SHARE_TEST, IONMEM_TEST,
Dezhi Kong288546e2019-05-16 17:02:38 +0800257 };
258
259 while (1) {
260 static struct option opts[] = {
Cao Jian510569c2019-08-16 14:01:44 +0800261 {"ion_mem_alloc", no_argument, 0, 'c'},
Dezhi Kong288546e2019-05-16 17:02:38 +0800262 {"alloc", no_argument, 0, 'a'},
263 {"alloc_flags", required_argument, 0, 'f'},
264 {"heap_mask", required_argument, 0, 'h'},
265 {"map", no_argument, 0, 'm'},
266 {"share", no_argument, 0, 's'},
267 {"len", required_argument, 0, 'l'},
268 {"align", required_argument, 0, 'g'},
269 {"map_flags", required_argument, 0, 'z'},
270 {"prot", required_argument, 0, 'p'},
271 };
272 int i = 0;
Dezhi Kong528d8cc2019-07-17 21:09:07 +0800273 c = getopt_long(argc, argv, "caf:h:l:mr:st", opts, &i);
Dezhi Kong288546e2019-05-16 17:02:38 +0800274 if (c == -1)
275 break;
276
277 switch (c) {
278 case 'l':
279 len = atol(optarg);
280 break;
281 case 'g':
282 align = atol(optarg);
283 break;
284 case 'z':
285 map_flags = 0;
286 map_flags |= strstr(optarg, "PROT_EXEC") ? PROT_EXEC : 0;
287 map_flags |= strstr(optarg, "PROT_READ") ? PROT_READ: 0;
288 map_flags |= strstr(optarg, "PROT_WRITE") ? PROT_WRITE: 0;
289 map_flags |= strstr(optarg, "PROT_NONE") ? PROT_NONE: 0;
290 break;
291 case 'p':
292 prot = 0;
293 prot |= strstr(optarg, "MAP_PRIVATE") ? MAP_PRIVATE : 0;
294 prot |= strstr(optarg, "MAP_SHARED") ? MAP_SHARED : 0;
295 break;
296 case 'f':
297 alloc_flags = atol(optarg);
298 break;
299 case 'h':
300 heap_mask = atol(optarg);
301 break;
302 case 'a':
303 test = ALLOC_TEST;
304 break;
305 case 'm':
306 test = MAP_TEST;
307 break;
308 case 's':
309 test = SHARE_TEST;
310 break;
Dezhi Kong528d8cc2019-07-17 21:09:07 +0800311 case 'c':
Cao Jian510569c2019-08-16 14:01:44 +0800312 test = IONMEM_TEST;
Dezhi Kong528d8cc2019-07-17 21:09:07 +0800313 break;
Dezhi Kong288546e2019-05-16 17:02:38 +0800314 }
315 }
316 printf("test %d, len %zu, align %zu, map_flags %d, prot %d, heap_mask %d,"
317 " alloc_flags %d\n", test, len, align, map_flags, prot,
318 heap_mask, alloc_flags);
319 switch (test) {
320 case ALLOC_TEST:
321 ion_alloc_test();
322 break;
323 case MAP_TEST:
324 ion_map_test();
325 break;
326 case SHARE_TEST:
327 ion_share_test();
328 break;
Cao Jian510569c2019-08-16 14:01:44 +0800329 case IONMEM_TEST:
330 _ionmem_alloc_test();
Dezhi Kong528d8cc2019-07-17 21:09:07 +0800331 break;
Dezhi Kong288546e2019-05-16 17:02:38 +0800332 default:
333 printf("must specify a test (alloc, map, share)\n");
334 }
335 return 0;
336}