1 #include <errno.h> 2 #include <fcntl.h> 3 #include <getopt.h> 4 #include <string.h> 5 #include <stdlib.h> 6 #include <stdio.h> 7 #include <sys/mman.h> 8 #include <sys/ioctl.h> 9 #include <sys/socket.h> 10 #include <sys/stat.h> 11 #include <sys/types.h> 12 #include <unistd.h> 13 14 #include <ion/ion.h> 15 #include <linux/ion.h> 16 #include <linux/omap_ion.h> 17 18 size_t len = 1024*1024, align = 0; 19 int prot = PROT_READ | PROT_WRITE; 20 int map_flags = MAP_SHARED; 21 int alloc_flags = 0; 22 int test = -1; 23 size_t width = 1024*1024, height = 1024*1024; 24 size_t stride; 25 26 int _ion_alloc_test(int *fd, struct ion_handle **handle) 27 { 28 int ret; 29 30 *fd = ion_open(); 31 if (*fd < 0) 32 return *fd; 33 34 ret = ion_alloc(*fd, len, align, alloc_flags, handle); 35 36 if (ret) 37 printf("%s failed: %s\n", __func__, strerror(ret)); 38 return ret; 39 } 40 41 void ion_alloc_test() 42 { 43 int fd, ret; 44 struct ion_handle *handle; 45 46 if(_ion_alloc_test(&fd, &handle)) 47 return; 48 49 ret = ion_free(fd, handle); 50 if (ret) { 51 printf("%s failed: %s %p\n", __func__, strerror(ret), handle); 52 return; 53 } 54 ion_close(fd); 55 printf("ion alloc test: passed\n"); 56 } 57 58 void ion_map_test() 59 { 60 int fd, map_fd, ret; 61 size_t i; 62 struct ion_handle *handle; 63 unsigned char *ptr; 64 65 if(_ion_alloc_test(&fd, &handle)) 66 return; 67 68 ret = ion_map(fd, handle, len, prot, map_flags, 0, &ptr, &map_fd); 69 if (ret) 70 return; 71 72 for (i = 0; i < len; i++) { 73 ptr[i] = (unsigned char)i; 74 } 75 for (i = 0; i < len; i++) 76 if (ptr[i] != (unsigned char)i) 77 printf("%s failed wrote %d read %d from mapped " 78 "memory\n", __func__, i, ptr[i]); 79 /* clean up properly */ 80 ret = ion_free(fd, handle); 81 ion_close(fd); 82 munmap(ptr, len); 83 close(map_fd); 84 85 _ion_alloc_test(&fd, &handle); 86 close(fd); 87 88 #if 0 89 munmap(ptr, len); 90 close(map_fd); 91 ion_close(fd); 92 93 _ion_alloc_test(len, align, flags, &fd, &handle); 94 close(map_fd); 95 ret = ion_map(fd, handle, len, prot, flags, 0, &ptr, &map_fd); 96 /* don't clean up */ 97 #endif 98 } 99 100 void ion_share_test() 101 102 { 103 struct ion_handle *handle; 104 int sd[2]; 105 int num_fd = 1; 106 struct iovec count_vec = { 107 .iov_base = &num_fd, 108 .iov_len = sizeof num_fd, 109 }; 110 char buf[CMSG_SPACE(sizeof(int))]; 111 socketpair(AF_UNIX, SOCK_STREAM, 0, sd); 112 if (fork()) { 113 struct msghdr msg = { 114 .msg_control = buf, 115 .msg_controllen = sizeof buf, 116 .msg_iov = &count_vec, 117 .msg_iovlen = 1, 118 }; 119 120 struct cmsghdr *cmsg; 121 int fd, share_fd, ret; 122 char *ptr; 123 /* parent */ 124 if(_ion_alloc_test(&fd, &handle)) 125 return; 126 ret = ion_share(fd, handle, &share_fd); 127 if (ret) 128 printf("share failed %s\n", strerror(errno)); 129 ptr = mmap(NULL, len, prot, map_flags, share_fd, 0); 130 if (ptr == MAP_FAILED) { 131 return; 132 } 133 strcpy(ptr, "master"); 134 cmsg = CMSG_FIRSTHDR(&msg); 135 cmsg->cmsg_level = SOL_SOCKET; 136 cmsg->cmsg_type = SCM_RIGHTS; 137 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 138 *(int *)CMSG_DATA(cmsg) = share_fd; 139 /* send the fd */ 140 printf("master? [%10s] should be [master]\n", ptr); 141 printf("master sending msg 1\n"); 142 sendmsg(sd[0], &msg, 0); 143 if (recvmsg(sd[0], &msg, 0) < 0) 144 perror("master recv msg 2"); 145 printf("master? [%10s] should be [child]\n", ptr); 146 147 /* send ping */ 148 sendmsg(sd[0], &msg, 0); 149 printf("master->master? [%10s]\n", ptr); 150 if (recvmsg(sd[0], &msg, 0) < 0) 151 perror("master recv 1"); 152 } else { 153 struct msghdr msg; 154 struct cmsghdr *cmsg; 155 char* ptr; 156 int fd, recv_fd; 157 char* child_buf[100]; 158 /* child */ 159 struct iovec count_vec = { 160 .iov_base = child_buf, 161 .iov_len = sizeof child_buf, 162 }; 163 164 struct msghdr child_msg = { 165 .msg_control = buf, 166 .msg_controllen = sizeof buf, 167 .msg_iov = &count_vec, 168 .msg_iovlen = 1, 169 }; 170 171 if (recvmsg(sd[1], &child_msg, 0) < 0) 172 perror("child recv msg 1"); 173 cmsg = CMSG_FIRSTHDR(&child_msg); 174 if (cmsg == NULL) { 175 printf("no cmsg rcvd in child"); 176 return; 177 } 178 recv_fd = *(int*)CMSG_DATA(cmsg); 179 if (recv_fd < 0) { 180 printf("could not get recv_fd from socket"); 181 return; 182 } 183 printf("child %d\n", recv_fd); 184 fd = ion_open(); 185 ptr = mmap(NULL, len, prot, map_flags, recv_fd, 0); 186 if (ptr == MAP_FAILED) { 187 return; 188 } 189 printf("child? [%10s] should be [master]\n", ptr); 190 strcpy(ptr, "child"); 191 printf("child sending msg 2\n"); 192 sendmsg(sd[1], &child_msg, 0); 193 } 194 } 195 196 int main(int argc, char* argv[]) { 197 int c; 198 enum tests { 199 ALLOC_TEST = 0, MAP_TEST, SHARE_TEST, 200 }; 201 202 while (1) { 203 static struct option opts[] = { 204 {"alloc", no_argument, 0, 'a'}, 205 {"alloc_flags", required_argument, 0, 'f'}, 206 {"map", no_argument, 0, 'm'}, 207 {"share", no_argument, 0, 's'}, 208 {"len", required_argument, 0, 'l'}, 209 {"align", required_argument, 0, 'g'}, 210 {"map_flags", required_argument, 0, 'z'}, 211 {"prot", required_argument, 0, 'p'}, 212 {"width", required_argument, 0, 'w'}, 213 {"height", required_argument, 0, 'h'}, 214 }; 215 int i = 0; 216 c = getopt_long(argc, argv, "af:h:l:mr:stw:", opts, &i); 217 if (c == -1) 218 break; 219 220 switch (c) { 221 case 'l': 222 len = atol(optarg); 223 break; 224 case 'g': 225 align = atol(optarg); 226 break; 227 case 'z': 228 map_flags = 0; 229 map_flags |= strstr(optarg, "PROT_EXEC") ? 230 PROT_EXEC : 0; 231 map_flags |= strstr(optarg, "PROT_READ") ? 232 PROT_READ: 0; 233 map_flags |= strstr(optarg, "PROT_WRITE") ? 234 PROT_WRITE: 0; 235 map_flags |= strstr(optarg, "PROT_NONE") ? 236 PROT_NONE: 0; 237 break; 238 case 'p': 239 prot = 0; 240 prot |= strstr(optarg, "MAP_PRIVATE") ? 241 MAP_PRIVATE : 0; 242 prot |= strstr(optarg, "MAP_SHARED") ? 243 MAP_PRIVATE : 0; 244 break; 245 case 'f': 246 alloc_flags = atol(optarg); 247 break; 248 case 'a': 249 test = ALLOC_TEST; 250 break; 251 case 'm': 252 test = MAP_TEST; 253 break; 254 case 's': 255 test = SHARE_TEST; 256 break; 257 case 'w': 258 width = atol(optarg); 259 break; 260 case 'h': 261 height = atol(optarg); 262 break; 263 } 264 } 265 printf("test %d, len %u, width %u, height %u align %u, " 266 "map_flags %d, prot %d, alloc_flags %d\n", test, len, width, 267 height, align, map_flags, prot, alloc_flags); 268 switch (test) { 269 case ALLOC_TEST: 270 ion_alloc_test(); 271 break; 272 case MAP_TEST: 273 ion_map_test(); 274 break; 275 case SHARE_TEST: 276 ion_share_test(); 277 break; 278 default: 279 printf("must specify a test (alloc, map, share)\n"); 280 } 281 return 0; 282 } 283