brintos

brintos / linux-shallow public Read only

0
0
Text · 6.2 KiB · 6062723 Raw
260 lines · c
1// SPDX-License-Identifier: GPL-2.02#define _GNU_SOURCE3#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       423#define NUM_ENTRIES     424#define MEMFD_SIZE      1024 /* in pages */25 26static unsigned int page_size;27 28static 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 57static 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 87static 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 96static 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 109static 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	}127err:128	munmap(addr1, memfd_size);129	munmap(addr2, NUM_ENTRIES * NUM_PAGES * getpagesize());130	return ret;131}132 133int 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	else180		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	else190		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	else200		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	else213		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	else231		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	else249		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