~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/drivers/dma-buf/udmabuf.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #define _GNU_SOURCE
  3 #define __EXPORTED_HEADERS__
  4 
  5 #include <stdio.h>
  6 #include <stdlib.h>
  7 #include <unistd.h>
  8 #include <string.h>
  9 #include <errno.h>
 10 #include <fcntl.h>
 11 #include <malloc.h>
 12 #include <stdbool.h>
 13 
 14 #include <sys/ioctl.h>
 15 #include <sys/syscall.h>
 16 #include <sys/mman.h>
 17 #include <linux/memfd.h>
 18 #include <linux/udmabuf.h>
 19 #include "../../kselftest.h"
 20 
 21 #define TEST_PREFIX     "drivers/dma-buf/udmabuf"
 22 #define NUM_PAGES       4
 23 #define NUM_ENTRIES     4
 24 #define MEMFD_SIZE      1024 /* in pages */
 25 
 26 static unsigned int page_size;
 27 
 28 static int create_memfd_with_seals(off64_t size, bool hpage)
 29 {
 30         int memfd, ret;
 31         unsigned int flags = MFD_ALLOW_SEALING;
 32 
 33         if (hpage)
 34                 flags |= MFD_HUGETLB;
 35 
 36         memfd = memfd_create("udmabuf-test", flags);
 37         if (memfd < 0) {
 38                 ksft_print_msg("%s: [skip,no-memfd]\n", TEST_PREFIX);
 39                 exit(KSFT_SKIP);
 40         }
 41 
 42         ret = fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK);
 43         if (ret < 0) {
 44                 ksft_print_msg("%s: [skip,fcntl-add-seals]\n", TEST_PREFIX);
 45                 exit(KSFT_SKIP);
 46         }
 47 
 48         ret = ftruncate(memfd, size);
 49         if (ret == -1) {
 50                 ksft_print_msg("%s: [FAIL,memfd-truncate]\n", TEST_PREFIX);
 51                 exit(KSFT_FAIL);
 52         }
 53 
 54         return memfd;
 55 }
 56 
 57 static int create_udmabuf_list(int devfd, int memfd, off64_t memfd_size)
 58 {
 59         struct udmabuf_create_list *list;
 60         int ubuf_fd, i;
 61 
 62         list = malloc(sizeof(struct udmabuf_create_list) +
 63                       sizeof(struct udmabuf_create_item) * NUM_ENTRIES);
 64         if (!list) {
 65                 ksft_print_msg("%s: [FAIL, udmabuf-malloc]\n", TEST_PREFIX);
 66                 exit(KSFT_FAIL);
 67         }
 68 
 69         for (i = 0; i < NUM_ENTRIES; i++) {
 70                 list->list[i].memfd  = memfd;
 71                 list->list[i].offset = i * (memfd_size / NUM_ENTRIES);
 72                 list->list[i].size   = getpagesize() * NUM_PAGES;
 73         }
 74 
 75         list->count = NUM_ENTRIES;
 76         list->flags = UDMABUF_FLAGS_CLOEXEC;
 77         ubuf_fd = ioctl(devfd, UDMABUF_CREATE_LIST, list);
 78         free(list);
 79         if (ubuf_fd < 0) {
 80                 ksft_print_msg("%s: [FAIL, udmabuf-create]\n", TEST_PREFIX);
 81                 exit(KSFT_FAIL);
 82         }
 83 
 84         return ubuf_fd;
 85 }
 86 
 87 static void write_to_memfd(void *addr, off64_t size, char chr)
 88 {
 89         int i;
 90 
 91         for (i = 0; i < size / page_size; i++) {
 92                 *((char *)addr + (i * page_size)) = chr;
 93         }
 94 }
 95 
 96 static void *mmap_fd(int fd, off64_t size)
 97 {
 98         void *addr;
 99 
100         addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
101         if (addr == MAP_FAILED) {
102                 ksft_print_msg("%s: ubuf_fd mmap fail\n", TEST_PREFIX);
103                 exit(KSFT_FAIL);
104         }
105 
106         return addr;
107 }
108 
109 static int compare_chunks(void *addr1, void *addr2, off64_t memfd_size)
110 {
111         off64_t off;
112         int i = 0, j, k = 0, ret = 0;
113         char char1, char2;
114 
115         while (i < NUM_ENTRIES) {
116                 off = i * (memfd_size / NUM_ENTRIES);
117                 for (j = 0; j < NUM_PAGES; j++, k++) {
118                         char1 = *((char *)addr1 + off + (j * getpagesize()));
119                         char2 = *((char *)addr2 + (k * getpagesize()));
120                         if (char1 != char2) {
121                                 ret = -1;
122                                 goto err;
123                         }
124                 }
125                 i++;
126         }
127 err:
128         munmap(addr1, memfd_size);
129         munmap(addr2, NUM_ENTRIES * NUM_PAGES * getpagesize());
130         return ret;
131 }
132 
133 int main(int argc, char *argv[])
134 {
135         struct udmabuf_create create;
136         int devfd, memfd, buf, ret;
137         off64_t size;
138         void *addr1, *addr2;
139 
140         ksft_print_header();
141         ksft_set_plan(6);
142 
143         devfd = open("/dev/udmabuf", O_RDWR);
144         if (devfd < 0) {
145                 ksft_print_msg(
146                         "%s: [skip,no-udmabuf: Unable to access DMA buffer device file]\n",
147                         TEST_PREFIX);
148                 exit(KSFT_SKIP);
149         }
150 
151         memfd = memfd_create("udmabuf-test", MFD_ALLOW_SEALING);
152         if (memfd < 0) {
153                 ksft_print_msg("%s: [skip,no-memfd]\n", TEST_PREFIX);
154                 exit(KSFT_SKIP);
155         }
156 
157         ret = fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK);
158         if (ret < 0) {
159                 ksft_print_msg("%s: [skip,fcntl-add-seals]\n", TEST_PREFIX);
160                 exit(KSFT_SKIP);
161         }
162 
163         size = getpagesize() * NUM_PAGES;
164         ret = ftruncate(memfd, size);
165         if (ret == -1) {
166                 ksft_print_msg("%s: [FAIL,memfd-truncate]\n", TEST_PREFIX);
167                 exit(KSFT_FAIL);
168         }
169 
170         memset(&create, 0, sizeof(create));
171 
172         /* should fail (offset not page aligned) */
173         create.memfd  = memfd;
174         create.offset = getpagesize()/2;
175         create.size   = getpagesize();
176         buf = ioctl(devfd, UDMABUF_CREATE, &create);
177         if (buf >= 0)
178                 ksft_test_result_fail("%s: [FAIL,test-1]\n", TEST_PREFIX);
179         else
180                 ksft_test_result_pass("%s: [PASS,test-1]\n", TEST_PREFIX);
181 
182         /* should fail (size not multiple of page) */
183         create.memfd  = memfd;
184         create.offset = 0;
185         create.size   = getpagesize()/2;
186         buf = ioctl(devfd, UDMABUF_CREATE, &create);
187         if (buf >= 0)
188                 ksft_test_result_fail("%s: [FAIL,test-2]\n", TEST_PREFIX);
189         else
190                 ksft_test_result_pass("%s: [PASS,test-2]\n", TEST_PREFIX);
191 
192         /* should fail (not memfd) */
193         create.memfd  = 0; /* stdin */
194         create.offset = 0;
195         create.size   = size;
196         buf = ioctl(devfd, UDMABUF_CREATE, &create);
197         if (buf >= 0)
198                 ksft_test_result_fail("%s: [FAIL,test-3]\n", TEST_PREFIX);
199         else
200                 ksft_test_result_pass("%s: [PASS,test-3]\n", TEST_PREFIX);
201 
202         /* should work */
203         page_size = getpagesize();
204         addr1 = mmap_fd(memfd, size);
205         write_to_memfd(addr1, size, 'a');
206         create.memfd  = memfd;
207         create.offset = 0;
208         create.size   = size;
209         buf = ioctl(devfd, UDMABUF_CREATE, &create);
210         if (buf < 0)
211                 ksft_test_result_fail("%s: [FAIL,test-4]\n", TEST_PREFIX);
212         else
213                 ksft_test_result_pass("%s: [PASS,test-4]\n", TEST_PREFIX);
214 
215         munmap(addr1, size);
216         close(buf);
217         close(memfd);
218 
219         /* should work (migration of 4k size pages)*/
220         size = MEMFD_SIZE * page_size;
221         memfd = create_memfd_with_seals(size, false);
222         addr1 = mmap_fd(memfd, size);
223         write_to_memfd(addr1, size, 'a');
224         buf = create_udmabuf_list(devfd, memfd, size);
225         addr2 = mmap_fd(buf, NUM_PAGES * NUM_ENTRIES * getpagesize());
226         write_to_memfd(addr1, size, 'b');
227         ret = compare_chunks(addr1, addr2, size);
228         if (ret < 0)
229                 ksft_test_result_fail("%s: [FAIL,test-5]\n", TEST_PREFIX);
230         else
231                 ksft_test_result_pass("%s: [PASS,test-5]\n", TEST_PREFIX);
232 
233         close(buf);
234         close(memfd);
235 
236         /* should work (migration of 2MB size huge pages)*/
237         page_size = getpagesize() * 512; /* 2 MB */
238         size = MEMFD_SIZE * page_size;
239         memfd = create_memfd_with_seals(size, true);
240         addr1 = mmap_fd(memfd, size);
241         write_to_memfd(addr1, size, 'a');
242         buf = create_udmabuf_list(devfd, memfd, size);
243         addr2 = mmap_fd(buf, NUM_PAGES * NUM_ENTRIES * getpagesize());
244         write_to_memfd(addr1, size, 'b');
245         ret = compare_chunks(addr1, addr2, size);
246         if (ret < 0)
247                 ksft_test_result_fail("%s: [FAIL,test-6]\n", TEST_PREFIX);
248         else
249                 ksft_test_result_pass("%s: [PASS,test-6]\n", TEST_PREFIX);
250 
251         close(buf);
252         close(memfd);
253         close(devfd);
254 
255         ksft_print_msg("%s: ok\n", TEST_PREFIX);
256         ksft_print_cnts();
257 
258         return 0;
259 }
260 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php