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 heap_mask = 1; 23 int test = -1; 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, heap_mask, 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 {"heap_mask", required_argument, 0, 'h'}, 207 {"map", no_argument, 0, 'm'}, 208 {"share", no_argument, 0, 's'}, 209 {"len", required_argument, 0, 'l'}, 210 {"align", required_argument, 0, 'g'}, 211 {"map_flags", required_argument, 0, 'z'}, 212 {"prot", required_argument, 0, 'p'}, 213 }; 214 int i = 0; 215 c = getopt_long(argc, argv, "af:h:l:mr:st", opts, &i); 216 if (c == -1) 217 break; 218 219 switch (c) { 220 case 'l': 221 len = atol(optarg); 222 break; 223 case 'g': 224 align = atol(optarg); 225 break; 226 case 'z': 227 map_flags = 0; 228 map_flags |= strstr(optarg, "PROT_EXEC") ? 229 PROT_EXEC : 0; 230 map_flags |= strstr(optarg, "PROT_READ") ? 231 PROT_READ: 0; 232 map_flags |= strstr(optarg, "PROT_WRITE") ? 233 PROT_WRITE: 0; 234 map_flags |= strstr(optarg, "PROT_NONE") ? 235 PROT_NONE: 0; 236 break; 237 case 'p': 238 prot = 0; 239 prot |= strstr(optarg, "MAP_PRIVATE") ? 240 MAP_PRIVATE : 0; 241 prot |= strstr(optarg, "MAP_SHARED") ? 242 MAP_PRIVATE : 0; 243 break; 244 case 'f': 245 alloc_flags = atol(optarg); 246 break; 247 case 'h': 248 heap_mask = atol(optarg); 249 break; 250 case 'a': 251 test = ALLOC_TEST; 252 break; 253 case 'm': 254 test = MAP_TEST; 255 break; 256 case 's': 257 test = SHARE_TEST; 258 break; 259 } 260 } 261 printf("test %d, len %u, align %u, map_flags %d, prot %d, heap_mask %d," 262 " alloc_flags %d\n", test, len, align, map_flags, prot, 263 heap_mask, alloc_flags); 264 switch (test) { 265 case ALLOC_TEST: 266 ion_alloc_test(); 267 break; 268 case MAP_TEST: 269 ion_map_test(); 270 break; 271 case SHARE_TEST: 272 ion_share_test(); 273 break; 274 default: 275 printf("must specify a test (alloc, map, share)\n"); 276 } 277 return 0; 278 } 279