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
13#include <sys/ioctl.h>
14#include <sys/syscall.h>
15#include <linux/memfd.h>
16#include <linux/udmabuf.h>
17
18#define TEST_PREFIX	"drivers/dma-buf/udmabuf"
19#define NUM_PAGES       4
20
21static int memfd_create(const char *name, unsigned int flags)
22{
23	return syscall(__NR_memfd_create, name, flags);
24}
25
26int main(int argc, char *argv[])
27{
28	struct udmabuf_create create;
29	int devfd, memfd, buf, ret;
30	off_t size;
31	void *mem;
32
33	devfd = open("/dev/udmabuf", O_RDWR);
34	if (devfd < 0) {
35		printf("%s: [skip,no-udmabuf: Unable to access DMA buffer device file]\n",
36		       TEST_PREFIX);
37		exit(77);
38	}
39
40	memfd = memfd_create("udmabuf-test", MFD_ALLOW_SEALING);
41	if (memfd < 0) {
42		printf("%s: [skip,no-memfd]\n", TEST_PREFIX);
43		exit(77);
44	}
45
46	ret = fcntl(memfd, F_ADD_SEALS, F_SEAL_SHRINK);
47	if (ret < 0) {
48		printf("%s: [skip,fcntl-add-seals]\n", TEST_PREFIX);
49		exit(77);
50	}
51
52
53	size = getpagesize() * NUM_PAGES;
54	ret = ftruncate(memfd, size);
55	if (ret == -1) {
56		printf("%s: [FAIL,memfd-truncate]\n", TEST_PREFIX);
57		exit(1);
58	}
59
60	memset(&create, 0, sizeof(create));
61
62	/* should fail (offset not page aligned) */
63	create.memfd  = memfd;
64	create.offset = getpagesize()/2;
65	create.size   = getpagesize();
66	buf = ioctl(devfd, UDMABUF_CREATE, &create);
67	if (buf >= 0) {
68		printf("%s: [FAIL,test-1]\n", TEST_PREFIX);
69		exit(1);
70	}
71
72	/* should fail (size not multiple of page) */
73	create.memfd  = memfd;
74	create.offset = 0;
75	create.size   = getpagesize()/2;
76	buf = ioctl(devfd, UDMABUF_CREATE, &create);
77	if (buf >= 0) {
78		printf("%s: [FAIL,test-2]\n", TEST_PREFIX);
79		exit(1);
80	}
81
82	/* should fail (not memfd) */
83	create.memfd  = 0; /* stdin */
84	create.offset = 0;
85	create.size   = size;
86	buf = ioctl(devfd, UDMABUF_CREATE, &create);
87	if (buf >= 0) {
88		printf("%s: [FAIL,test-3]\n", TEST_PREFIX);
89		exit(1);
90	}
91
92	/* should work */
93	create.memfd  = memfd;
94	create.offset = 0;
95	create.size   = size;
96	buf = ioctl(devfd, UDMABUF_CREATE, &create);
97	if (buf < 0) {
98		printf("%s: [FAIL,test-4]\n", TEST_PREFIX);
99		exit(1);
100	}
101
102	fprintf(stderr, "%s: ok\n", TEST_PREFIX);
103	close(buf);
104	close(memfd);
105	close(devfd);
106	return 0;
107}
108