xref: /linux/tools/testing/selftests/iommu/iommufd.c (revision f6154d8babbb8a98f0d3ea325aafae2e33bfd8be)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES */
3 #include <stdlib.h>
4 #include <sys/mman.h>
5 #include <sys/eventfd.h>
6 
7 #define __EXPORTED_HEADERS__
8 #include <linux/vfio.h>
9 
10 #include "iommufd_utils.h"
11 
12 static unsigned long HUGEPAGE_SIZE;
13 
14 #define MOCK_PAGE_SIZE (PAGE_SIZE / 2)
15 
16 static unsigned long get_huge_page_size(void)
17 {
18 	char buf[80];
19 	int ret;
20 	int fd;
21 
22 	fd = open("/sys/kernel/mm/transparent_hugepage/hpage_pmd_size",
23 		  O_RDONLY);
24 	if (fd < 0)
25 		return 2 * 1024 * 1024;
26 
27 	ret = read(fd, buf, sizeof(buf));
28 	close(fd);
29 	if (ret <= 0 || ret == sizeof(buf))
30 		return 2 * 1024 * 1024;
31 	buf[ret] = 0;
32 	return strtoul(buf, NULL, 10);
33 }
34 
35 static __attribute__((constructor)) void setup_sizes(void)
36 {
37 	void *vrc;
38 	int rc;
39 
40 	PAGE_SIZE = sysconf(_SC_PAGE_SIZE);
41 	HUGEPAGE_SIZE = get_huge_page_size();
42 
43 	BUFFER_SIZE = PAGE_SIZE * 16;
44 	rc = posix_memalign(&buffer, HUGEPAGE_SIZE, BUFFER_SIZE);
45 	assert(!rc);
46 	assert(buffer);
47 	assert((uintptr_t)buffer % HUGEPAGE_SIZE == 0);
48 	vrc = mmap(buffer, BUFFER_SIZE, PROT_READ | PROT_WRITE,
49 		   MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
50 	assert(vrc == buffer);
51 }
52 
53 FIXTURE(iommufd)
54 {
55 	int fd;
56 };
57 
58 FIXTURE_SETUP(iommufd)
59 {
60 	self->fd = open("/dev/iommu", O_RDWR);
61 	ASSERT_NE(-1, self->fd);
62 }
63 
64 FIXTURE_TEARDOWN(iommufd)
65 {
66 	teardown_iommufd(self->fd, _metadata);
67 }
68 
69 TEST_F(iommufd, simple_close)
70 {
71 }
72 
73 TEST_F(iommufd, cmd_fail)
74 {
75 	struct iommu_destroy cmd = { .size = sizeof(cmd), .id = 0 };
76 
77 	/* object id is invalid */
78 	EXPECT_ERRNO(ENOENT, _test_ioctl_destroy(self->fd, 0));
79 	/* Bad pointer */
80 	EXPECT_ERRNO(EFAULT, ioctl(self->fd, IOMMU_DESTROY, NULL));
81 	/* Unknown ioctl */
82 	EXPECT_ERRNO(ENOTTY,
83 		     ioctl(self->fd, _IO(IOMMUFD_TYPE, IOMMUFD_CMD_BASE - 1),
84 			   &cmd));
85 }
86 
87 TEST_F(iommufd, cmd_length)
88 {
89 #define TEST_LENGTH(_struct, _ioctl, _last)                              \
90 	{                                                                \
91 		size_t min_size = offsetofend(struct _struct, _last);    \
92 		struct {                                                 \
93 			struct _struct cmd;                              \
94 			uint8_t extra;                                   \
95 		} cmd = { .cmd = { .size = min_size - 1 },               \
96 			  .extra = UINT8_MAX };                          \
97 		int old_errno;                                           \
98 		int rc;                                                  \
99 									 \
100 		EXPECT_ERRNO(EINVAL, ioctl(self->fd, _ioctl, &cmd));     \
101 		cmd.cmd.size = sizeof(struct _struct) + 1;               \
102 		EXPECT_ERRNO(E2BIG, ioctl(self->fd, _ioctl, &cmd));      \
103 		cmd.cmd.size = sizeof(struct _struct);                   \
104 		rc = ioctl(self->fd, _ioctl, &cmd);                      \
105 		old_errno = errno;                                       \
106 		cmd.cmd.size = sizeof(struct _struct) + 1;               \
107 		cmd.extra = 0;                                           \
108 		if (rc) {                                                \
109 			EXPECT_ERRNO(old_errno,                          \
110 				     ioctl(self->fd, _ioctl, &cmd));     \
111 		} else {                                                 \
112 			ASSERT_EQ(0, ioctl(self->fd, _ioctl, &cmd));     \
113 		}                                                        \
114 	}
115 
116 	TEST_LENGTH(iommu_destroy, IOMMU_DESTROY, id);
117 	TEST_LENGTH(iommu_hw_info, IOMMU_GET_HW_INFO, __reserved);
118 	TEST_LENGTH(iommu_hwpt_alloc, IOMMU_HWPT_ALLOC, __reserved);
119 	TEST_LENGTH(iommu_ioas_alloc, IOMMU_IOAS_ALLOC, out_ioas_id);
120 	TEST_LENGTH(iommu_ioas_iova_ranges, IOMMU_IOAS_IOVA_RANGES,
121 		    out_iova_alignment);
122 	TEST_LENGTH(iommu_ioas_allow_iovas, IOMMU_IOAS_ALLOW_IOVAS,
123 		    allowed_iovas);
124 	TEST_LENGTH(iommu_ioas_map, IOMMU_IOAS_MAP, iova);
125 	TEST_LENGTH(iommu_ioas_copy, IOMMU_IOAS_COPY, src_iova);
126 	TEST_LENGTH(iommu_ioas_unmap, IOMMU_IOAS_UNMAP, length);
127 	TEST_LENGTH(iommu_option, IOMMU_OPTION, val64);
128 	TEST_LENGTH(iommu_vfio_ioas, IOMMU_VFIO_IOAS, __reserved);
129 #undef TEST_LENGTH
130 }
131 
132 TEST_F(iommufd, cmd_ex_fail)
133 {
134 	struct {
135 		struct iommu_destroy cmd;
136 		__u64 future;
137 	} cmd = { .cmd = { .size = sizeof(cmd), .id = 0 } };
138 
139 	/* object id is invalid and command is longer */
140 	EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_DESTROY, &cmd));
141 	/* future area is non-zero */
142 	cmd.future = 1;
143 	EXPECT_ERRNO(E2BIG, ioctl(self->fd, IOMMU_DESTROY, &cmd));
144 	/* Original command "works" */
145 	cmd.cmd.size = sizeof(cmd.cmd);
146 	EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_DESTROY, &cmd));
147 	/* Short command fails */
148 	cmd.cmd.size = sizeof(cmd.cmd) - 1;
149 	EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_DESTROY, &cmd));
150 }
151 
152 TEST_F(iommufd, global_options)
153 {
154 	struct iommu_option cmd = {
155 		.size = sizeof(cmd),
156 		.option_id = IOMMU_OPTION_RLIMIT_MODE,
157 		.op = IOMMU_OPTION_OP_GET,
158 		.val64 = 1,
159 	};
160 
161 	cmd.option_id = IOMMU_OPTION_RLIMIT_MODE;
162 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
163 	ASSERT_EQ(0, cmd.val64);
164 
165 	/* This requires root */
166 	cmd.op = IOMMU_OPTION_OP_SET;
167 	cmd.val64 = 1;
168 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
169 	cmd.val64 = 2;
170 	EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_OPTION, &cmd));
171 
172 	cmd.op = IOMMU_OPTION_OP_GET;
173 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
174 	ASSERT_EQ(1, cmd.val64);
175 
176 	cmd.op = IOMMU_OPTION_OP_SET;
177 	cmd.val64 = 0;
178 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
179 
180 	cmd.op = IOMMU_OPTION_OP_GET;
181 	cmd.option_id = IOMMU_OPTION_HUGE_PAGES;
182 	EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_OPTION, &cmd));
183 	cmd.op = IOMMU_OPTION_OP_SET;
184 	EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_OPTION, &cmd));
185 }
186 
187 FIXTURE(iommufd_ioas)
188 {
189 	int fd;
190 	uint32_t ioas_id;
191 	uint32_t stdev_id;
192 	uint32_t hwpt_id;
193 	uint32_t device_id;
194 	uint64_t base_iova;
195 };
196 
197 FIXTURE_VARIANT(iommufd_ioas)
198 {
199 	unsigned int mock_domains;
200 	unsigned int memory_limit;
201 };
202 
203 FIXTURE_SETUP(iommufd_ioas)
204 {
205 	unsigned int i;
206 
207 
208 	self->fd = open("/dev/iommu", O_RDWR);
209 	ASSERT_NE(-1, self->fd);
210 	test_ioctl_ioas_alloc(&self->ioas_id);
211 
212 	if (!variant->memory_limit) {
213 		test_ioctl_set_default_memory_limit();
214 	} else {
215 		test_ioctl_set_temp_memory_limit(variant->memory_limit);
216 	}
217 
218 	for (i = 0; i != variant->mock_domains; i++) {
219 		test_cmd_mock_domain(self->ioas_id, &self->stdev_id,
220 				     &self->hwpt_id, &self->device_id);
221 		self->base_iova = MOCK_APERTURE_START;
222 	}
223 }
224 
225 FIXTURE_TEARDOWN(iommufd_ioas)
226 {
227 	test_ioctl_set_default_memory_limit();
228 	teardown_iommufd(self->fd, _metadata);
229 }
230 
231 FIXTURE_VARIANT_ADD(iommufd_ioas, no_domain)
232 {
233 };
234 
235 FIXTURE_VARIANT_ADD(iommufd_ioas, mock_domain)
236 {
237 	.mock_domains = 1,
238 };
239 
240 FIXTURE_VARIANT_ADD(iommufd_ioas, two_mock_domain)
241 {
242 	.mock_domains = 2,
243 };
244 
245 FIXTURE_VARIANT_ADD(iommufd_ioas, mock_domain_limit)
246 {
247 	.mock_domains = 1,
248 	.memory_limit = 16,
249 };
250 
251 TEST_F(iommufd_ioas, ioas_auto_destroy)
252 {
253 }
254 
255 TEST_F(iommufd_ioas, ioas_destroy)
256 {
257 	if (self->stdev_id) {
258 		/* IOAS cannot be freed while a device has a HWPT using it */
259 		EXPECT_ERRNO(EBUSY,
260 			     _test_ioctl_destroy(self->fd, self->ioas_id));
261 	} else {
262 		/* Can allocate and manually free an IOAS table */
263 		test_ioctl_destroy(self->ioas_id);
264 	}
265 }
266 
267 TEST_F(iommufd_ioas, alloc_hwpt_nested)
268 {
269 	const uint32_t min_data_len =
270 		offsetofend(struct iommu_hwpt_selftest, iotlb);
271 	struct iommu_hwpt_selftest data = {
272 		.iotlb = IOMMU_TEST_IOTLB_DEFAULT,
273 	};
274 	uint32_t nested_hwpt_id[2] = {};
275 	uint32_t parent_hwpt_id = 0;
276 	uint32_t parent_hwpt_id_not_work = 0;
277 	uint32_t test_hwpt_id = 0;
278 
279 	if (self->device_id) {
280 		/* Negative tests */
281 		test_err_hwpt_alloc(ENOENT, self->ioas_id, self->device_id, 0,
282 				    &test_hwpt_id);
283 		test_err_hwpt_alloc(EINVAL, self->device_id, self->device_id, 0,
284 				    &test_hwpt_id);
285 
286 		test_cmd_hwpt_alloc(self->device_id, self->ioas_id,
287 				    IOMMU_HWPT_ALLOC_NEST_PARENT,
288 				    &parent_hwpt_id);
289 
290 		test_cmd_hwpt_alloc(self->device_id, self->ioas_id, 0,
291 				    &parent_hwpt_id_not_work);
292 
293 		/* Negative nested tests */
294 		test_err_hwpt_alloc_nested(EINVAL, self->device_id,
295 					   parent_hwpt_id, 0,
296 					   &nested_hwpt_id[0],
297 					   IOMMU_HWPT_DATA_NONE, &data,
298 					   sizeof(data));
299 		test_err_hwpt_alloc_nested(EOPNOTSUPP, self->device_id,
300 					   parent_hwpt_id, 0,
301 					   &nested_hwpt_id[0],
302 					   IOMMU_HWPT_DATA_SELFTEST + 1, &data,
303 					   sizeof(data));
304 		test_err_hwpt_alloc_nested(EINVAL, self->device_id,
305 					   parent_hwpt_id, 0,
306 					   &nested_hwpt_id[0],
307 					   IOMMU_HWPT_DATA_SELFTEST, &data,
308 					   min_data_len - 1);
309 		test_err_hwpt_alloc_nested(EFAULT, self->device_id,
310 					   parent_hwpt_id, 0,
311 					   &nested_hwpt_id[0],
312 					   IOMMU_HWPT_DATA_SELFTEST, NULL,
313 					   sizeof(data));
314 		test_err_hwpt_alloc_nested(
315 			EOPNOTSUPP, self->device_id, parent_hwpt_id,
316 			IOMMU_HWPT_ALLOC_NEST_PARENT, &nested_hwpt_id[0],
317 			IOMMU_HWPT_DATA_SELFTEST, &data, sizeof(data));
318 		test_err_hwpt_alloc_nested(EINVAL, self->device_id,
319 					   parent_hwpt_id_not_work, 0,
320 					   &nested_hwpt_id[0],
321 					   IOMMU_HWPT_DATA_SELFTEST, &data,
322 					   sizeof(data));
323 
324 		/* Allocate two nested hwpts sharing one common parent hwpt */
325 		test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id, 0,
326 					   &nested_hwpt_id[0],
327 					   IOMMU_HWPT_DATA_SELFTEST, &data,
328 					   sizeof(data));
329 		test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id, 0,
330 					   &nested_hwpt_id[1],
331 					   IOMMU_HWPT_DATA_SELFTEST, &data,
332 					   sizeof(data));
333 
334 		/* Negative test: a nested hwpt on top of a nested hwpt */
335 		test_err_hwpt_alloc_nested(EINVAL, self->device_id,
336 					   nested_hwpt_id[0], 0, &test_hwpt_id,
337 					   IOMMU_HWPT_DATA_SELFTEST, &data,
338 					   sizeof(data));
339 		/* Negative test: parent hwpt now cannot be freed */
340 		EXPECT_ERRNO(EBUSY,
341 			     _test_ioctl_destroy(self->fd, parent_hwpt_id));
342 
343 		/* Attach device to nested_hwpt_id[0] that then will be busy */
344 		test_cmd_mock_domain_replace(self->stdev_id, nested_hwpt_id[0]);
345 		EXPECT_ERRNO(EBUSY,
346 			     _test_ioctl_destroy(self->fd, nested_hwpt_id[0]));
347 
348 		/* Switch from nested_hwpt_id[0] to nested_hwpt_id[1] */
349 		test_cmd_mock_domain_replace(self->stdev_id, nested_hwpt_id[1]);
350 		EXPECT_ERRNO(EBUSY,
351 			     _test_ioctl_destroy(self->fd, nested_hwpt_id[1]));
352 		test_ioctl_destroy(nested_hwpt_id[0]);
353 
354 		/* Detach from nested_hwpt_id[1] and destroy it */
355 		test_cmd_mock_domain_replace(self->stdev_id, parent_hwpt_id);
356 		test_ioctl_destroy(nested_hwpt_id[1]);
357 
358 		/* Detach from the parent hw_pagetable and destroy it */
359 		test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
360 		test_ioctl_destroy(parent_hwpt_id);
361 		test_ioctl_destroy(parent_hwpt_id_not_work);
362 	} else {
363 		test_err_hwpt_alloc(ENOENT, self->device_id, self->ioas_id, 0,
364 				    &parent_hwpt_id);
365 		test_err_hwpt_alloc_nested(ENOENT, self->device_id,
366 					   parent_hwpt_id, 0,
367 					   &nested_hwpt_id[0],
368 					   IOMMU_HWPT_DATA_SELFTEST, &data,
369 					   sizeof(data));
370 		test_err_hwpt_alloc_nested(ENOENT, self->device_id,
371 					   parent_hwpt_id, 0,
372 					   &nested_hwpt_id[1],
373 					   IOMMU_HWPT_DATA_SELFTEST, &data,
374 					   sizeof(data));
375 		test_err_mock_domain_replace(ENOENT, self->stdev_id,
376 					     nested_hwpt_id[0]);
377 		test_err_mock_domain_replace(ENOENT, self->stdev_id,
378 					     nested_hwpt_id[1]);
379 	}
380 }
381 
382 TEST_F(iommufd_ioas, hwpt_attach)
383 {
384 	/* Create a device attached directly to a hwpt */
385 	if (self->stdev_id) {
386 		test_cmd_mock_domain(self->hwpt_id, NULL, NULL, NULL);
387 	} else {
388 		test_err_mock_domain(ENOENT, self->hwpt_id, NULL, NULL);
389 	}
390 }
391 
392 TEST_F(iommufd_ioas, ioas_area_destroy)
393 {
394 	/* Adding an area does not change ability to destroy */
395 	test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE, self->base_iova);
396 	if (self->stdev_id)
397 		EXPECT_ERRNO(EBUSY,
398 			     _test_ioctl_destroy(self->fd, self->ioas_id));
399 	else
400 		test_ioctl_destroy(self->ioas_id);
401 }
402 
403 TEST_F(iommufd_ioas, ioas_area_auto_destroy)
404 {
405 	int i;
406 
407 	/* Can allocate and automatically free an IOAS table with many areas */
408 	for (i = 0; i != 10; i++) {
409 		test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE,
410 					  self->base_iova + i * PAGE_SIZE);
411 	}
412 }
413 
414 TEST_F(iommufd_ioas, get_hw_info)
415 {
416 	struct iommu_test_hw_info buffer_exact;
417 	struct iommu_test_hw_info_buffer_larger {
418 		struct iommu_test_hw_info info;
419 		uint64_t trailing_bytes;
420 	} buffer_larger;
421 	struct iommu_test_hw_info_buffer_smaller {
422 		__u32 flags;
423 	} buffer_smaller;
424 
425 	if (self->device_id) {
426 		/* Provide a zero-size user_buffer */
427 		test_cmd_get_hw_info(self->device_id, NULL, 0);
428 		/* Provide a user_buffer with exact size */
429 		test_cmd_get_hw_info(self->device_id, &buffer_exact, sizeof(buffer_exact));
430 		/*
431 		 * Provide a user_buffer with size larger than the exact size to check if
432 		 * kernel zero the trailing bytes.
433 		 */
434 		test_cmd_get_hw_info(self->device_id, &buffer_larger, sizeof(buffer_larger));
435 		/*
436 		 * Provide a user_buffer with size smaller than the exact size to check if
437 		 * the fields within the size range still gets updated.
438 		 */
439 		test_cmd_get_hw_info(self->device_id, &buffer_smaller, sizeof(buffer_smaller));
440 	} else {
441 		test_err_get_hw_info(ENOENT, self->device_id,
442 				     &buffer_exact, sizeof(buffer_exact));
443 		test_err_get_hw_info(ENOENT, self->device_id,
444 				     &buffer_larger, sizeof(buffer_larger));
445 	}
446 }
447 
448 TEST_F(iommufd_ioas, area)
449 {
450 	int i;
451 
452 	/* Unmap fails if nothing is mapped */
453 	for (i = 0; i != 10; i++)
454 		test_err_ioctl_ioas_unmap(ENOENT, i * PAGE_SIZE, PAGE_SIZE);
455 
456 	/* Unmap works */
457 	for (i = 0; i != 10; i++)
458 		test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE,
459 					  self->base_iova + i * PAGE_SIZE);
460 	for (i = 0; i != 10; i++)
461 		test_ioctl_ioas_unmap(self->base_iova + i * PAGE_SIZE,
462 				      PAGE_SIZE);
463 
464 	/* Split fails */
465 	test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE * 2,
466 				  self->base_iova + 16 * PAGE_SIZE);
467 	test_err_ioctl_ioas_unmap(ENOENT, self->base_iova + 16 * PAGE_SIZE,
468 				  PAGE_SIZE);
469 	test_err_ioctl_ioas_unmap(ENOENT, self->base_iova + 17 * PAGE_SIZE,
470 				  PAGE_SIZE);
471 
472 	/* Over map fails */
473 	test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE * 2,
474 				      self->base_iova + 16 * PAGE_SIZE);
475 	test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE,
476 				      self->base_iova + 16 * PAGE_SIZE);
477 	test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE,
478 				      self->base_iova + 17 * PAGE_SIZE);
479 	test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE * 2,
480 				      self->base_iova + 15 * PAGE_SIZE);
481 	test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE * 3,
482 				      self->base_iova + 15 * PAGE_SIZE);
483 
484 	/* unmap all works */
485 	test_ioctl_ioas_unmap(0, UINT64_MAX);
486 
487 	/* Unmap all succeeds on an empty IOAS */
488 	test_ioctl_ioas_unmap(0, UINT64_MAX);
489 }
490 
491 TEST_F(iommufd_ioas, unmap_fully_contained_areas)
492 {
493 	uint64_t unmap_len;
494 	int i;
495 
496 	/* Give no_domain some space to rewind base_iova */
497 	self->base_iova += 4 * PAGE_SIZE;
498 
499 	for (i = 0; i != 4; i++)
500 		test_ioctl_ioas_map_fixed(buffer, 8 * PAGE_SIZE,
501 					  self->base_iova + i * 16 * PAGE_SIZE);
502 
503 	/* Unmap not fully contained area doesn't work */
504 	test_err_ioctl_ioas_unmap(ENOENT, self->base_iova - 4 * PAGE_SIZE,
505 				  8 * PAGE_SIZE);
506 	test_err_ioctl_ioas_unmap(ENOENT,
507 				  self->base_iova + 3 * 16 * PAGE_SIZE +
508 					  8 * PAGE_SIZE - 4 * PAGE_SIZE,
509 				  8 * PAGE_SIZE);
510 
511 	/* Unmap fully contained areas works */
512 	ASSERT_EQ(0, _test_ioctl_ioas_unmap(self->fd, self->ioas_id,
513 					    self->base_iova - 4 * PAGE_SIZE,
514 					    3 * 16 * PAGE_SIZE + 8 * PAGE_SIZE +
515 						    4 * PAGE_SIZE,
516 					    &unmap_len));
517 	ASSERT_EQ(32 * PAGE_SIZE, unmap_len);
518 }
519 
520 TEST_F(iommufd_ioas, area_auto_iova)
521 {
522 	struct iommu_test_cmd test_cmd = {
523 		.size = sizeof(test_cmd),
524 		.op = IOMMU_TEST_OP_ADD_RESERVED,
525 		.id = self->ioas_id,
526 		.add_reserved = { .start = PAGE_SIZE * 4,
527 				  .length = PAGE_SIZE * 100 },
528 	};
529 	struct iommu_iova_range ranges[1] = {};
530 	struct iommu_ioas_allow_iovas allow_cmd = {
531 		.size = sizeof(allow_cmd),
532 		.ioas_id = self->ioas_id,
533 		.num_iovas = 1,
534 		.allowed_iovas = (uintptr_t)ranges,
535 	};
536 	__u64 iovas[10];
537 	int i;
538 
539 	/* Simple 4k pages */
540 	for (i = 0; i != 10; i++)
541 		test_ioctl_ioas_map(buffer, PAGE_SIZE, &iovas[i]);
542 	for (i = 0; i != 10; i++)
543 		test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE);
544 
545 	/* Kernel automatically aligns IOVAs properly */
546 	for (i = 0; i != 10; i++) {
547 		size_t length = PAGE_SIZE * (i + 1);
548 
549 		if (self->stdev_id) {
550 			test_ioctl_ioas_map(buffer, length, &iovas[i]);
551 		} else {
552 			test_ioctl_ioas_map((void *)(1UL << 31), length,
553 					    &iovas[i]);
554 		}
555 		EXPECT_EQ(0, iovas[i] % (1UL << (ffs(length) - 1)));
556 	}
557 	for (i = 0; i != 10; i++)
558 		test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE * (i + 1));
559 
560 	/* Avoids a reserved region */
561 	ASSERT_EQ(0,
562 		  ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
563 			&test_cmd));
564 	for (i = 0; i != 10; i++) {
565 		size_t length = PAGE_SIZE * (i + 1);
566 
567 		test_ioctl_ioas_map(buffer, length, &iovas[i]);
568 		EXPECT_EQ(0, iovas[i] % (1UL << (ffs(length) - 1)));
569 		EXPECT_EQ(false,
570 			  iovas[i] > test_cmd.add_reserved.start &&
571 				  iovas[i] <
572 					  test_cmd.add_reserved.start +
573 						  test_cmd.add_reserved.length);
574 	}
575 	for (i = 0; i != 10; i++)
576 		test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE * (i + 1));
577 
578 	/* Allowed region intersects with a reserved region */
579 	ranges[0].start = PAGE_SIZE;
580 	ranges[0].last = PAGE_SIZE * 600;
581 	EXPECT_ERRNO(EADDRINUSE,
582 		     ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
583 
584 	/* Allocate from an allowed region */
585 	if (self->stdev_id) {
586 		ranges[0].start = MOCK_APERTURE_START + PAGE_SIZE;
587 		ranges[0].last = MOCK_APERTURE_START + PAGE_SIZE * 600 - 1;
588 	} else {
589 		ranges[0].start = PAGE_SIZE * 200;
590 		ranges[0].last = PAGE_SIZE * 600 - 1;
591 	}
592 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
593 	for (i = 0; i != 10; i++) {
594 		size_t length = PAGE_SIZE * (i + 1);
595 
596 		test_ioctl_ioas_map(buffer, length, &iovas[i]);
597 		EXPECT_EQ(0, iovas[i] % (1UL << (ffs(length) - 1)));
598 		EXPECT_EQ(true, iovas[i] >= ranges[0].start);
599 		EXPECT_EQ(true, iovas[i] <= ranges[0].last);
600 		EXPECT_EQ(true, iovas[i] + length > ranges[0].start);
601 		EXPECT_EQ(true, iovas[i] + length <= ranges[0].last + 1);
602 	}
603 	for (i = 0; i != 10; i++)
604 		test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE * (i + 1));
605 }
606 
607 TEST_F(iommufd_ioas, area_allowed)
608 {
609 	struct iommu_test_cmd test_cmd = {
610 		.size = sizeof(test_cmd),
611 		.op = IOMMU_TEST_OP_ADD_RESERVED,
612 		.id = self->ioas_id,
613 		.add_reserved = { .start = PAGE_SIZE * 4,
614 				  .length = PAGE_SIZE * 100 },
615 	};
616 	struct iommu_iova_range ranges[1] = {};
617 	struct iommu_ioas_allow_iovas allow_cmd = {
618 		.size = sizeof(allow_cmd),
619 		.ioas_id = self->ioas_id,
620 		.num_iovas = 1,
621 		.allowed_iovas = (uintptr_t)ranges,
622 	};
623 
624 	/* Reserved intersects an allowed */
625 	allow_cmd.num_iovas = 1;
626 	ranges[0].start = self->base_iova;
627 	ranges[0].last = ranges[0].start + PAGE_SIZE * 600;
628 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
629 	test_cmd.add_reserved.start = ranges[0].start + PAGE_SIZE;
630 	test_cmd.add_reserved.length = PAGE_SIZE;
631 	EXPECT_ERRNO(EADDRINUSE,
632 		     ioctl(self->fd,
633 			   _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
634 			   &test_cmd));
635 	allow_cmd.num_iovas = 0;
636 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
637 
638 	/* Allowed intersects a reserved */
639 	ASSERT_EQ(0,
640 		  ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
641 			&test_cmd));
642 	allow_cmd.num_iovas = 1;
643 	ranges[0].start = self->base_iova;
644 	ranges[0].last = ranges[0].start + PAGE_SIZE * 600;
645 	EXPECT_ERRNO(EADDRINUSE,
646 		     ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
647 }
648 
649 TEST_F(iommufd_ioas, copy_area)
650 {
651 	struct iommu_ioas_copy copy_cmd = {
652 		.size = sizeof(copy_cmd),
653 		.flags = IOMMU_IOAS_MAP_FIXED_IOVA,
654 		.dst_ioas_id = self->ioas_id,
655 		.src_ioas_id = self->ioas_id,
656 		.length = PAGE_SIZE,
657 	};
658 
659 	test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE, self->base_iova);
660 
661 	/* Copy inside a single IOAS */
662 	copy_cmd.src_iova = self->base_iova;
663 	copy_cmd.dst_iova = self->base_iova + PAGE_SIZE;
664 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
665 
666 	/* Copy between IOAS's */
667 	copy_cmd.src_iova = self->base_iova;
668 	copy_cmd.dst_iova = 0;
669 	test_ioctl_ioas_alloc(&copy_cmd.dst_ioas_id);
670 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
671 }
672 
673 TEST_F(iommufd_ioas, iova_ranges)
674 {
675 	struct iommu_test_cmd test_cmd = {
676 		.size = sizeof(test_cmd),
677 		.op = IOMMU_TEST_OP_ADD_RESERVED,
678 		.id = self->ioas_id,
679 		.add_reserved = { .start = PAGE_SIZE, .length = PAGE_SIZE },
680 	};
681 	struct iommu_iova_range *ranges = buffer;
682 	struct iommu_ioas_iova_ranges ranges_cmd = {
683 		.size = sizeof(ranges_cmd),
684 		.ioas_id = self->ioas_id,
685 		.num_iovas = BUFFER_SIZE / sizeof(*ranges),
686 		.allowed_iovas = (uintptr_t)ranges,
687 	};
688 
689 	/* Range can be read */
690 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
691 	EXPECT_EQ(1, ranges_cmd.num_iovas);
692 	if (!self->stdev_id) {
693 		EXPECT_EQ(0, ranges[0].start);
694 		EXPECT_EQ(SIZE_MAX, ranges[0].last);
695 		EXPECT_EQ(1, ranges_cmd.out_iova_alignment);
696 	} else {
697 		EXPECT_EQ(MOCK_APERTURE_START, ranges[0].start);
698 		EXPECT_EQ(MOCK_APERTURE_LAST, ranges[0].last);
699 		EXPECT_EQ(MOCK_PAGE_SIZE, ranges_cmd.out_iova_alignment);
700 	}
701 
702 	/* Buffer too small */
703 	memset(ranges, 0, BUFFER_SIZE);
704 	ranges_cmd.num_iovas = 0;
705 	EXPECT_ERRNO(EMSGSIZE,
706 		     ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
707 	EXPECT_EQ(1, ranges_cmd.num_iovas);
708 	EXPECT_EQ(0, ranges[0].start);
709 	EXPECT_EQ(0, ranges[0].last);
710 
711 	/* 2 ranges */
712 	ASSERT_EQ(0,
713 		  ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
714 			&test_cmd));
715 	ranges_cmd.num_iovas = BUFFER_SIZE / sizeof(*ranges);
716 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
717 	if (!self->stdev_id) {
718 		EXPECT_EQ(2, ranges_cmd.num_iovas);
719 		EXPECT_EQ(0, ranges[0].start);
720 		EXPECT_EQ(PAGE_SIZE - 1, ranges[0].last);
721 		EXPECT_EQ(PAGE_SIZE * 2, ranges[1].start);
722 		EXPECT_EQ(SIZE_MAX, ranges[1].last);
723 	} else {
724 		EXPECT_EQ(1, ranges_cmd.num_iovas);
725 		EXPECT_EQ(MOCK_APERTURE_START, ranges[0].start);
726 		EXPECT_EQ(MOCK_APERTURE_LAST, ranges[0].last);
727 	}
728 
729 	/* Buffer too small */
730 	memset(ranges, 0, BUFFER_SIZE);
731 	ranges_cmd.num_iovas = 1;
732 	if (!self->stdev_id) {
733 		EXPECT_ERRNO(EMSGSIZE, ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES,
734 					     &ranges_cmd));
735 		EXPECT_EQ(2, ranges_cmd.num_iovas);
736 		EXPECT_EQ(0, ranges[0].start);
737 		EXPECT_EQ(PAGE_SIZE - 1, ranges[0].last);
738 	} else {
739 		ASSERT_EQ(0,
740 			  ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
741 		EXPECT_EQ(1, ranges_cmd.num_iovas);
742 		EXPECT_EQ(MOCK_APERTURE_START, ranges[0].start);
743 		EXPECT_EQ(MOCK_APERTURE_LAST, ranges[0].last);
744 	}
745 	EXPECT_EQ(0, ranges[1].start);
746 	EXPECT_EQ(0, ranges[1].last);
747 }
748 
749 TEST_F(iommufd_ioas, access_domain_destory)
750 {
751 	struct iommu_test_cmd access_cmd = {
752 		.size = sizeof(access_cmd),
753 		.op = IOMMU_TEST_OP_ACCESS_PAGES,
754 		.access_pages = { .iova = self->base_iova + PAGE_SIZE,
755 				  .length = PAGE_SIZE},
756 	};
757 	size_t buf_size = 2 * HUGEPAGE_SIZE;
758 	uint8_t *buf;
759 
760 	buf = mmap(0, buf_size, PROT_READ | PROT_WRITE,
761 		   MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, -1,
762 		   0);
763 	ASSERT_NE(MAP_FAILED, buf);
764 	test_ioctl_ioas_map_fixed(buf, buf_size, self->base_iova);
765 
766 	test_cmd_create_access(self->ioas_id, &access_cmd.id,
767 			       MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
768 	access_cmd.access_pages.uptr = (uintptr_t)buf + PAGE_SIZE;
769 	ASSERT_EQ(0,
770 		  ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
771 			&access_cmd));
772 
773 	/* Causes a complicated unpin across a huge page boundary */
774 	if (self->stdev_id)
775 		test_ioctl_destroy(self->stdev_id);
776 
777 	test_cmd_destroy_access_pages(
778 		access_cmd.id, access_cmd.access_pages.out_access_pages_id);
779 	test_cmd_destroy_access(access_cmd.id);
780 	ASSERT_EQ(0, munmap(buf, buf_size));
781 }
782 
783 TEST_F(iommufd_ioas, access_pin)
784 {
785 	struct iommu_test_cmd access_cmd = {
786 		.size = sizeof(access_cmd),
787 		.op = IOMMU_TEST_OP_ACCESS_PAGES,
788 		.access_pages = { .iova = MOCK_APERTURE_START,
789 				  .length = BUFFER_SIZE,
790 				  .uptr = (uintptr_t)buffer },
791 	};
792 	struct iommu_test_cmd check_map_cmd = {
793 		.size = sizeof(check_map_cmd),
794 		.op = IOMMU_TEST_OP_MD_CHECK_MAP,
795 		.check_map = { .iova = MOCK_APERTURE_START,
796 			       .length = BUFFER_SIZE,
797 			       .uptr = (uintptr_t)buffer },
798 	};
799 	uint32_t access_pages_id;
800 	unsigned int npages;
801 
802 	test_cmd_create_access(self->ioas_id, &access_cmd.id,
803 			       MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
804 
805 	for (npages = 1; npages < BUFFER_SIZE / PAGE_SIZE; npages++) {
806 		uint32_t mock_stdev_id;
807 		uint32_t mock_hwpt_id;
808 
809 		access_cmd.access_pages.length = npages * PAGE_SIZE;
810 
811 		/* Single map/unmap */
812 		test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE,
813 					  MOCK_APERTURE_START);
814 		ASSERT_EQ(0, ioctl(self->fd,
815 				   _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
816 				   &access_cmd));
817 		test_cmd_destroy_access_pages(
818 			access_cmd.id,
819 			access_cmd.access_pages.out_access_pages_id);
820 
821 		/* Double user */
822 		ASSERT_EQ(0, ioctl(self->fd,
823 				   _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
824 				   &access_cmd));
825 		access_pages_id = access_cmd.access_pages.out_access_pages_id;
826 		ASSERT_EQ(0, ioctl(self->fd,
827 				   _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
828 				   &access_cmd));
829 		test_cmd_destroy_access_pages(
830 			access_cmd.id,
831 			access_cmd.access_pages.out_access_pages_id);
832 		test_cmd_destroy_access_pages(access_cmd.id, access_pages_id);
833 
834 		/* Add/remove a domain with a user */
835 		ASSERT_EQ(0, ioctl(self->fd,
836 				   _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
837 				   &access_cmd));
838 		test_cmd_mock_domain(self->ioas_id, &mock_stdev_id,
839 				     &mock_hwpt_id, NULL);
840 		check_map_cmd.id = mock_hwpt_id;
841 		ASSERT_EQ(0, ioctl(self->fd,
842 				   _IOMMU_TEST_CMD(IOMMU_TEST_OP_MD_CHECK_MAP),
843 				   &check_map_cmd));
844 
845 		test_ioctl_destroy(mock_stdev_id);
846 		test_cmd_destroy_access_pages(
847 			access_cmd.id,
848 			access_cmd.access_pages.out_access_pages_id);
849 
850 		test_ioctl_ioas_unmap(MOCK_APERTURE_START, BUFFER_SIZE);
851 	}
852 	test_cmd_destroy_access(access_cmd.id);
853 }
854 
855 TEST_F(iommufd_ioas, access_pin_unmap)
856 {
857 	struct iommu_test_cmd access_pages_cmd = {
858 		.size = sizeof(access_pages_cmd),
859 		.op = IOMMU_TEST_OP_ACCESS_PAGES,
860 		.access_pages = { .iova = MOCK_APERTURE_START,
861 				  .length = BUFFER_SIZE,
862 				  .uptr = (uintptr_t)buffer },
863 	};
864 
865 	test_cmd_create_access(self->ioas_id, &access_pages_cmd.id,
866 			       MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
867 	test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE, MOCK_APERTURE_START);
868 	ASSERT_EQ(0,
869 		  ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
870 			&access_pages_cmd));
871 
872 	/* Trigger the unmap op */
873 	test_ioctl_ioas_unmap(MOCK_APERTURE_START, BUFFER_SIZE);
874 
875 	/* kernel removed the item for us */
876 	test_err_destroy_access_pages(
877 		ENOENT, access_pages_cmd.id,
878 		access_pages_cmd.access_pages.out_access_pages_id);
879 }
880 
881 static void check_access_rw(struct __test_metadata *_metadata, int fd,
882 			    unsigned int access_id, uint64_t iova,
883 			    unsigned int def_flags)
884 {
885 	uint16_t tmp[32];
886 	struct iommu_test_cmd access_cmd = {
887 		.size = sizeof(access_cmd),
888 		.op = IOMMU_TEST_OP_ACCESS_RW,
889 		.id = access_id,
890 		.access_rw = { .uptr = (uintptr_t)tmp },
891 	};
892 	uint16_t *buffer16 = buffer;
893 	unsigned int i;
894 	void *tmp2;
895 
896 	for (i = 0; i != BUFFER_SIZE / sizeof(*buffer16); i++)
897 		buffer16[i] = rand();
898 
899 	for (access_cmd.access_rw.iova = iova + PAGE_SIZE - 50;
900 	     access_cmd.access_rw.iova < iova + PAGE_SIZE + 50;
901 	     access_cmd.access_rw.iova++) {
902 		for (access_cmd.access_rw.length = 1;
903 		     access_cmd.access_rw.length < sizeof(tmp);
904 		     access_cmd.access_rw.length++) {
905 			access_cmd.access_rw.flags = def_flags;
906 			ASSERT_EQ(0, ioctl(fd,
907 					   _IOMMU_TEST_CMD(
908 						   IOMMU_TEST_OP_ACCESS_RW),
909 					   &access_cmd));
910 			ASSERT_EQ(0,
911 				  memcmp(buffer + (access_cmd.access_rw.iova -
912 						   iova),
913 					 tmp, access_cmd.access_rw.length));
914 
915 			for (i = 0; i != ARRAY_SIZE(tmp); i++)
916 				tmp[i] = rand();
917 			access_cmd.access_rw.flags = def_flags |
918 						     MOCK_ACCESS_RW_WRITE;
919 			ASSERT_EQ(0, ioctl(fd,
920 					   _IOMMU_TEST_CMD(
921 						   IOMMU_TEST_OP_ACCESS_RW),
922 					   &access_cmd));
923 			ASSERT_EQ(0,
924 				  memcmp(buffer + (access_cmd.access_rw.iova -
925 						   iova),
926 					 tmp, access_cmd.access_rw.length));
927 		}
928 	}
929 
930 	/* Multi-page test */
931 	tmp2 = malloc(BUFFER_SIZE);
932 	ASSERT_NE(NULL, tmp2);
933 	access_cmd.access_rw.iova = iova;
934 	access_cmd.access_rw.length = BUFFER_SIZE;
935 	access_cmd.access_rw.flags = def_flags;
936 	access_cmd.access_rw.uptr = (uintptr_t)tmp2;
937 	ASSERT_EQ(0, ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_RW),
938 			   &access_cmd));
939 	ASSERT_EQ(0, memcmp(buffer, tmp2, access_cmd.access_rw.length));
940 	free(tmp2);
941 }
942 
943 TEST_F(iommufd_ioas, access_rw)
944 {
945 	__u32 access_id;
946 	__u64 iova;
947 
948 	test_cmd_create_access(self->ioas_id, &access_id, 0);
949 	test_ioctl_ioas_map(buffer, BUFFER_SIZE, &iova);
950 	check_access_rw(_metadata, self->fd, access_id, iova, 0);
951 	check_access_rw(_metadata, self->fd, access_id, iova,
952 			MOCK_ACCESS_RW_SLOW_PATH);
953 	test_ioctl_ioas_unmap(iova, BUFFER_SIZE);
954 	test_cmd_destroy_access(access_id);
955 }
956 
957 TEST_F(iommufd_ioas, access_rw_unaligned)
958 {
959 	__u32 access_id;
960 	__u64 iova;
961 
962 	test_cmd_create_access(self->ioas_id, &access_id, 0);
963 
964 	/* Unaligned pages */
965 	iova = self->base_iova + MOCK_PAGE_SIZE;
966 	test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE, iova);
967 	check_access_rw(_metadata, self->fd, access_id, iova, 0);
968 	test_ioctl_ioas_unmap(iova, BUFFER_SIZE);
969 	test_cmd_destroy_access(access_id);
970 }
971 
972 TEST_F(iommufd_ioas, fork_gone)
973 {
974 	__u32 access_id;
975 	pid_t child;
976 
977 	test_cmd_create_access(self->ioas_id, &access_id, 0);
978 
979 	/* Create a mapping with a different mm */
980 	child = fork();
981 	if (!child) {
982 		test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE,
983 					  MOCK_APERTURE_START);
984 		exit(0);
985 	}
986 	ASSERT_NE(-1, child);
987 	ASSERT_EQ(child, waitpid(child, NULL, 0));
988 
989 	if (self->stdev_id) {
990 		/*
991 		 * If a domain already existed then everything was pinned within
992 		 * the fork, so this copies from one domain to another.
993 		 */
994 		test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
995 		check_access_rw(_metadata, self->fd, access_id,
996 				MOCK_APERTURE_START, 0);
997 
998 	} else {
999 		/*
1000 		 * Otherwise we need to actually pin pages which can't happen
1001 		 * since the fork is gone.
1002 		 */
1003 		test_err_mock_domain(EFAULT, self->ioas_id, NULL, NULL);
1004 	}
1005 
1006 	test_cmd_destroy_access(access_id);
1007 }
1008 
1009 TEST_F(iommufd_ioas, fork_present)
1010 {
1011 	__u32 access_id;
1012 	int pipefds[2];
1013 	uint64_t tmp;
1014 	pid_t child;
1015 	int efd;
1016 
1017 	test_cmd_create_access(self->ioas_id, &access_id, 0);
1018 
1019 	ASSERT_EQ(0, pipe2(pipefds, O_CLOEXEC));
1020 	efd = eventfd(0, EFD_CLOEXEC);
1021 	ASSERT_NE(-1, efd);
1022 
1023 	/* Create a mapping with a different mm */
1024 	child = fork();
1025 	if (!child) {
1026 		__u64 iova;
1027 		uint64_t one = 1;
1028 
1029 		close(pipefds[1]);
1030 		test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE,
1031 					  MOCK_APERTURE_START);
1032 		if (write(efd, &one, sizeof(one)) != sizeof(one))
1033 			exit(100);
1034 		if (read(pipefds[0], &iova, 1) != 1)
1035 			exit(100);
1036 		exit(0);
1037 	}
1038 	close(pipefds[0]);
1039 	ASSERT_NE(-1, child);
1040 	ASSERT_EQ(8, read(efd, &tmp, sizeof(tmp)));
1041 
1042 	/* Read pages from the remote process */
1043 	test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
1044 	check_access_rw(_metadata, self->fd, access_id, MOCK_APERTURE_START, 0);
1045 
1046 	ASSERT_EQ(0, close(pipefds[1]));
1047 	ASSERT_EQ(child, waitpid(child, NULL, 0));
1048 
1049 	test_cmd_destroy_access(access_id);
1050 }
1051 
1052 TEST_F(iommufd_ioas, ioas_option_huge_pages)
1053 {
1054 	struct iommu_option cmd = {
1055 		.size = sizeof(cmd),
1056 		.option_id = IOMMU_OPTION_HUGE_PAGES,
1057 		.op = IOMMU_OPTION_OP_GET,
1058 		.val64 = 3,
1059 		.object_id = self->ioas_id,
1060 	};
1061 
1062 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1063 	ASSERT_EQ(1, cmd.val64);
1064 
1065 	cmd.op = IOMMU_OPTION_OP_SET;
1066 	cmd.val64 = 0;
1067 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1068 
1069 	cmd.op = IOMMU_OPTION_OP_GET;
1070 	cmd.val64 = 3;
1071 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1072 	ASSERT_EQ(0, cmd.val64);
1073 
1074 	cmd.op = IOMMU_OPTION_OP_SET;
1075 	cmd.val64 = 2;
1076 	EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_OPTION, &cmd));
1077 
1078 	cmd.op = IOMMU_OPTION_OP_SET;
1079 	cmd.val64 = 1;
1080 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1081 }
1082 
1083 TEST_F(iommufd_ioas, ioas_iova_alloc)
1084 {
1085 	unsigned int length;
1086 	__u64 iova;
1087 
1088 	for (length = 1; length != PAGE_SIZE * 2; length++) {
1089 		if (variant->mock_domains && (length % MOCK_PAGE_SIZE)) {
1090 			test_err_ioctl_ioas_map(EINVAL, buffer, length, &iova);
1091 		} else {
1092 			test_ioctl_ioas_map(buffer, length, &iova);
1093 			test_ioctl_ioas_unmap(iova, length);
1094 		}
1095 	}
1096 }
1097 
1098 TEST_F(iommufd_ioas, ioas_align_change)
1099 {
1100 	struct iommu_option cmd = {
1101 		.size = sizeof(cmd),
1102 		.option_id = IOMMU_OPTION_HUGE_PAGES,
1103 		.op = IOMMU_OPTION_OP_SET,
1104 		.object_id = self->ioas_id,
1105 		/* 0 means everything must be aligned to PAGE_SIZE */
1106 		.val64 = 0,
1107 	};
1108 
1109 	/*
1110 	 * We cannot upgrade the alignment using OPTION_HUGE_PAGES when a domain
1111 	 * and map are present.
1112 	 */
1113 	if (variant->mock_domains)
1114 		return;
1115 
1116 	/*
1117 	 * We can upgrade to PAGE_SIZE alignment when things are aligned right
1118 	 */
1119 	test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE, MOCK_APERTURE_START);
1120 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1121 
1122 	/* Misalignment is rejected at map time */
1123 	test_err_ioctl_ioas_map_fixed(EINVAL, buffer + MOCK_PAGE_SIZE,
1124 				      PAGE_SIZE,
1125 				      MOCK_APERTURE_START + PAGE_SIZE);
1126 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1127 
1128 	/* Reduce alignment */
1129 	cmd.val64 = 1;
1130 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1131 
1132 	/* Confirm misalignment is rejected during alignment upgrade */
1133 	test_ioctl_ioas_map_fixed(buffer + MOCK_PAGE_SIZE, PAGE_SIZE,
1134 				  MOCK_APERTURE_START + PAGE_SIZE);
1135 	cmd.val64 = 0;
1136 	EXPECT_ERRNO(EADDRINUSE, ioctl(self->fd, IOMMU_OPTION, &cmd));
1137 
1138 	test_ioctl_ioas_unmap(MOCK_APERTURE_START + PAGE_SIZE, PAGE_SIZE);
1139 	test_ioctl_ioas_unmap(MOCK_APERTURE_START, PAGE_SIZE);
1140 }
1141 
1142 TEST_F(iommufd_ioas, copy_sweep)
1143 {
1144 	struct iommu_ioas_copy copy_cmd = {
1145 		.size = sizeof(copy_cmd),
1146 		.flags = IOMMU_IOAS_MAP_FIXED_IOVA,
1147 		.src_ioas_id = self->ioas_id,
1148 		.dst_iova = MOCK_APERTURE_START,
1149 		.length = MOCK_PAGE_SIZE,
1150 	};
1151 	unsigned int dst_ioas_id;
1152 	uint64_t last_iova;
1153 	uint64_t iova;
1154 
1155 	test_ioctl_ioas_alloc(&dst_ioas_id);
1156 	copy_cmd.dst_ioas_id = dst_ioas_id;
1157 
1158 	if (variant->mock_domains)
1159 		last_iova = MOCK_APERTURE_START + BUFFER_SIZE - 1;
1160 	else
1161 		last_iova = MOCK_APERTURE_START + BUFFER_SIZE - 2;
1162 
1163 	test_ioctl_ioas_map_fixed(buffer, last_iova - MOCK_APERTURE_START + 1,
1164 				  MOCK_APERTURE_START);
1165 
1166 	for (iova = MOCK_APERTURE_START - PAGE_SIZE; iova <= last_iova;
1167 	     iova += 511) {
1168 		copy_cmd.src_iova = iova;
1169 		if (iova < MOCK_APERTURE_START ||
1170 		    iova + copy_cmd.length - 1 > last_iova) {
1171 			EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_IOAS_COPY,
1172 						   &copy_cmd));
1173 		} else {
1174 			ASSERT_EQ(0,
1175 				  ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
1176 			test_ioctl_ioas_unmap_id(dst_ioas_id, copy_cmd.dst_iova,
1177 						 copy_cmd.length);
1178 		}
1179 	}
1180 
1181 	test_ioctl_destroy(dst_ioas_id);
1182 }
1183 
1184 FIXTURE(iommufd_mock_domain)
1185 {
1186 	int fd;
1187 	uint32_t ioas_id;
1188 	uint32_t hwpt_id;
1189 	uint32_t hwpt_ids[2];
1190 	uint32_t stdev_ids[2];
1191 	uint32_t idev_ids[2];
1192 	int mmap_flags;
1193 	size_t mmap_buf_size;
1194 };
1195 
1196 FIXTURE_VARIANT(iommufd_mock_domain)
1197 {
1198 	unsigned int mock_domains;
1199 	bool hugepages;
1200 };
1201 
1202 FIXTURE_SETUP(iommufd_mock_domain)
1203 {
1204 	unsigned int i;
1205 
1206 	self->fd = open("/dev/iommu", O_RDWR);
1207 	ASSERT_NE(-1, self->fd);
1208 	test_ioctl_ioas_alloc(&self->ioas_id);
1209 
1210 	ASSERT_GE(ARRAY_SIZE(self->hwpt_ids), variant->mock_domains);
1211 
1212 	for (i = 0; i != variant->mock_domains; i++)
1213 		test_cmd_mock_domain(self->ioas_id, &self->stdev_ids[i],
1214 				     &self->hwpt_ids[i], &self->idev_ids[i]);
1215 	self->hwpt_id = self->hwpt_ids[0];
1216 
1217 	self->mmap_flags = MAP_SHARED | MAP_ANONYMOUS;
1218 	self->mmap_buf_size = PAGE_SIZE * 8;
1219 	if (variant->hugepages) {
1220 		/*
1221 		 * MAP_POPULATE will cause the kernel to fail mmap if THPs are
1222 		 * not available.
1223 		 */
1224 		self->mmap_flags |= MAP_HUGETLB | MAP_POPULATE;
1225 		self->mmap_buf_size = HUGEPAGE_SIZE * 2;
1226 	}
1227 }
1228 
1229 FIXTURE_TEARDOWN(iommufd_mock_domain)
1230 {
1231 	teardown_iommufd(self->fd, _metadata);
1232 }
1233 
1234 FIXTURE_VARIANT_ADD(iommufd_mock_domain, one_domain)
1235 {
1236 	.mock_domains = 1,
1237 	.hugepages = false,
1238 };
1239 
1240 FIXTURE_VARIANT_ADD(iommufd_mock_domain, two_domains)
1241 {
1242 	.mock_domains = 2,
1243 	.hugepages = false,
1244 };
1245 
1246 FIXTURE_VARIANT_ADD(iommufd_mock_domain, one_domain_hugepage)
1247 {
1248 	.mock_domains = 1,
1249 	.hugepages = true,
1250 };
1251 
1252 FIXTURE_VARIANT_ADD(iommufd_mock_domain, two_domains_hugepage)
1253 {
1254 	.mock_domains = 2,
1255 	.hugepages = true,
1256 };
1257 
1258 /* Have the kernel check that the user pages made it to the iommu_domain */
1259 #define check_mock_iova(_ptr, _iova, _length)                                \
1260 	({                                                                   \
1261 		struct iommu_test_cmd check_map_cmd = {                      \
1262 			.size = sizeof(check_map_cmd),                       \
1263 			.op = IOMMU_TEST_OP_MD_CHECK_MAP,                    \
1264 			.id = self->hwpt_id,                                 \
1265 			.check_map = { .iova = _iova,                        \
1266 				       .length = _length,                    \
1267 				       .uptr = (uintptr_t)(_ptr) },          \
1268 		};                                                           \
1269 		ASSERT_EQ(0,                                                 \
1270 			  ioctl(self->fd,                                    \
1271 				_IOMMU_TEST_CMD(IOMMU_TEST_OP_MD_CHECK_MAP), \
1272 				&check_map_cmd));                            \
1273 		if (self->hwpt_ids[1]) {                                     \
1274 			check_map_cmd.id = self->hwpt_ids[1];                \
1275 			ASSERT_EQ(0,                                         \
1276 				  ioctl(self->fd,                            \
1277 					_IOMMU_TEST_CMD(                     \
1278 						IOMMU_TEST_OP_MD_CHECK_MAP), \
1279 					&check_map_cmd));                    \
1280 		}                                                            \
1281 	})
1282 
1283 TEST_F(iommufd_mock_domain, basic)
1284 {
1285 	size_t buf_size = self->mmap_buf_size;
1286 	uint8_t *buf;
1287 	__u64 iova;
1288 
1289 	/* Simple one page map */
1290 	test_ioctl_ioas_map(buffer, PAGE_SIZE, &iova);
1291 	check_mock_iova(buffer, iova, PAGE_SIZE);
1292 
1293 	buf = mmap(0, buf_size, PROT_READ | PROT_WRITE, self->mmap_flags, -1,
1294 		   0);
1295 	ASSERT_NE(MAP_FAILED, buf);
1296 
1297 	/* EFAULT half way through mapping */
1298 	ASSERT_EQ(0, munmap(buf + buf_size / 2, buf_size / 2));
1299 	test_err_ioctl_ioas_map(EFAULT, buf, buf_size, &iova);
1300 
1301 	/* EFAULT on first page */
1302 	ASSERT_EQ(0, munmap(buf, buf_size / 2));
1303 	test_err_ioctl_ioas_map(EFAULT, buf, buf_size, &iova);
1304 }
1305 
1306 TEST_F(iommufd_mock_domain, ro_unshare)
1307 {
1308 	uint8_t *buf;
1309 	__u64 iova;
1310 	int fd;
1311 
1312 	fd = open("/proc/self/exe", O_RDONLY);
1313 	ASSERT_NE(-1, fd);
1314 
1315 	buf = mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
1316 	ASSERT_NE(MAP_FAILED, buf);
1317 	close(fd);
1318 
1319 	/*
1320 	 * There have been lots of changes to the "unshare" mechanism in
1321 	 * get_user_pages(), make sure it works right. The write to the page
1322 	 * after we map it for reading should not change the assigned PFN.
1323 	 */
1324 	ASSERT_EQ(0,
1325 		  _test_ioctl_ioas_map(self->fd, self->ioas_id, buf, PAGE_SIZE,
1326 				       &iova, IOMMU_IOAS_MAP_READABLE));
1327 	check_mock_iova(buf, iova, PAGE_SIZE);
1328 	memset(buf, 1, PAGE_SIZE);
1329 	check_mock_iova(buf, iova, PAGE_SIZE);
1330 	ASSERT_EQ(0, munmap(buf, PAGE_SIZE));
1331 }
1332 
1333 TEST_F(iommufd_mock_domain, all_aligns)
1334 {
1335 	size_t test_step = variant->hugepages ? (self->mmap_buf_size / 16) :
1336 						MOCK_PAGE_SIZE;
1337 	size_t buf_size = self->mmap_buf_size;
1338 	unsigned int start;
1339 	unsigned int end;
1340 	uint8_t *buf;
1341 
1342 	buf = mmap(0, buf_size, PROT_READ | PROT_WRITE, self->mmap_flags, -1,
1343 		   0);
1344 	ASSERT_NE(MAP_FAILED, buf);
1345 	check_refs(buf, buf_size, 0);
1346 
1347 	/*
1348 	 * Map every combination of page size and alignment within a big region,
1349 	 * less for hugepage case as it takes so long to finish.
1350 	 */
1351 	for (start = 0; start < buf_size; start += test_step) {
1352 		if (variant->hugepages)
1353 			end = buf_size;
1354 		else
1355 			end = start + MOCK_PAGE_SIZE;
1356 		for (; end < buf_size; end += MOCK_PAGE_SIZE) {
1357 			size_t length = end - start;
1358 			__u64 iova;
1359 
1360 			test_ioctl_ioas_map(buf + start, length, &iova);
1361 			check_mock_iova(buf + start, iova, length);
1362 			check_refs(buf + start / PAGE_SIZE * PAGE_SIZE,
1363 				   end / PAGE_SIZE * PAGE_SIZE -
1364 					   start / PAGE_SIZE * PAGE_SIZE,
1365 				   1);
1366 
1367 			test_ioctl_ioas_unmap(iova, length);
1368 		}
1369 	}
1370 	check_refs(buf, buf_size, 0);
1371 	ASSERT_EQ(0, munmap(buf, buf_size));
1372 }
1373 
1374 TEST_F(iommufd_mock_domain, all_aligns_copy)
1375 {
1376 	size_t test_step = variant->hugepages ? self->mmap_buf_size / 16 :
1377 						MOCK_PAGE_SIZE;
1378 	size_t buf_size = self->mmap_buf_size;
1379 	unsigned int start;
1380 	unsigned int end;
1381 	uint8_t *buf;
1382 
1383 	buf = mmap(0, buf_size, PROT_READ | PROT_WRITE, self->mmap_flags, -1,
1384 		   0);
1385 	ASSERT_NE(MAP_FAILED, buf);
1386 	check_refs(buf, buf_size, 0);
1387 
1388 	/*
1389 	 * Map every combination of page size and alignment within a big region,
1390 	 * less for hugepage case as it takes so long to finish.
1391 	 */
1392 	for (start = 0; start < buf_size; start += test_step) {
1393 		if (variant->hugepages)
1394 			end = buf_size;
1395 		else
1396 			end = start + MOCK_PAGE_SIZE;
1397 		for (; end < buf_size; end += MOCK_PAGE_SIZE) {
1398 			size_t length = end - start;
1399 			unsigned int old_id;
1400 			uint32_t mock_stdev_id;
1401 			__u64 iova;
1402 
1403 			test_ioctl_ioas_map(buf + start, length, &iova);
1404 
1405 			/* Add and destroy a domain while the area exists */
1406 			old_id = self->hwpt_ids[1];
1407 			test_cmd_mock_domain(self->ioas_id, &mock_stdev_id,
1408 					     &self->hwpt_ids[1], NULL);
1409 
1410 			check_mock_iova(buf + start, iova, length);
1411 			check_refs(buf + start / PAGE_SIZE * PAGE_SIZE,
1412 				   end / PAGE_SIZE * PAGE_SIZE -
1413 					   start / PAGE_SIZE * PAGE_SIZE,
1414 				   1);
1415 
1416 			test_ioctl_destroy(mock_stdev_id);
1417 			self->hwpt_ids[1] = old_id;
1418 
1419 			test_ioctl_ioas_unmap(iova, length);
1420 		}
1421 	}
1422 	check_refs(buf, buf_size, 0);
1423 	ASSERT_EQ(0, munmap(buf, buf_size));
1424 }
1425 
1426 TEST_F(iommufd_mock_domain, user_copy)
1427 {
1428 	struct iommu_test_cmd access_cmd = {
1429 		.size = sizeof(access_cmd),
1430 		.op = IOMMU_TEST_OP_ACCESS_PAGES,
1431 		.access_pages = { .length = BUFFER_SIZE,
1432 				  .uptr = (uintptr_t)buffer },
1433 	};
1434 	struct iommu_ioas_copy copy_cmd = {
1435 		.size = sizeof(copy_cmd),
1436 		.flags = IOMMU_IOAS_MAP_FIXED_IOVA,
1437 		.dst_ioas_id = self->ioas_id,
1438 		.dst_iova = MOCK_APERTURE_START,
1439 		.length = BUFFER_SIZE,
1440 	};
1441 	struct iommu_ioas_unmap unmap_cmd = {
1442 		.size = sizeof(unmap_cmd),
1443 		.ioas_id = self->ioas_id,
1444 		.iova = MOCK_APERTURE_START,
1445 		.length = BUFFER_SIZE,
1446 	};
1447 	unsigned int new_ioas_id, ioas_id;
1448 
1449 	/* Pin the pages in an IOAS with no domains then copy to an IOAS with domains */
1450 	test_ioctl_ioas_alloc(&ioas_id);
1451 	test_ioctl_ioas_map_id(ioas_id, buffer, BUFFER_SIZE,
1452 			       &copy_cmd.src_iova);
1453 
1454 	test_cmd_create_access(ioas_id, &access_cmd.id,
1455 			       MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
1456 
1457 	access_cmd.access_pages.iova = copy_cmd.src_iova;
1458 	ASSERT_EQ(0,
1459 		  ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
1460 			&access_cmd));
1461 	copy_cmd.src_ioas_id = ioas_id;
1462 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
1463 	check_mock_iova(buffer, MOCK_APERTURE_START, BUFFER_SIZE);
1464 
1465 	/* Now replace the ioas with a new one */
1466 	test_ioctl_ioas_alloc(&new_ioas_id);
1467 	test_ioctl_ioas_map_id(new_ioas_id, buffer, BUFFER_SIZE,
1468 			       &copy_cmd.src_iova);
1469 	test_cmd_access_replace_ioas(access_cmd.id, new_ioas_id);
1470 
1471 	/* Destroy the old ioas and cleanup copied mapping */
1472 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_UNMAP, &unmap_cmd));
1473 	test_ioctl_destroy(ioas_id);
1474 
1475 	/* Then run the same test again with the new ioas */
1476 	access_cmd.access_pages.iova = copy_cmd.src_iova;
1477 	ASSERT_EQ(0,
1478 		  ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
1479 			&access_cmd));
1480 	copy_cmd.src_ioas_id = new_ioas_id;
1481 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
1482 	check_mock_iova(buffer, MOCK_APERTURE_START, BUFFER_SIZE);
1483 
1484 	test_cmd_destroy_access_pages(
1485 		access_cmd.id, access_cmd.access_pages.out_access_pages_id);
1486 	test_cmd_destroy_access(access_cmd.id);
1487 
1488 	test_ioctl_destroy(new_ioas_id);
1489 }
1490 
1491 TEST_F(iommufd_mock_domain, replace)
1492 {
1493 	uint32_t ioas_id;
1494 
1495 	test_ioctl_ioas_alloc(&ioas_id);
1496 
1497 	test_cmd_mock_domain_replace(self->stdev_ids[0], ioas_id);
1498 
1499 	/*
1500 	 * Replacing the IOAS causes the prior HWPT to be deallocated, thus we
1501 	 * should get enoent when we try to use it.
1502 	 */
1503 	if (variant->mock_domains == 1)
1504 		test_err_mock_domain_replace(ENOENT, self->stdev_ids[0],
1505 					     self->hwpt_ids[0]);
1506 
1507 	test_cmd_mock_domain_replace(self->stdev_ids[0], ioas_id);
1508 	if (variant->mock_domains >= 2) {
1509 		test_cmd_mock_domain_replace(self->stdev_ids[0],
1510 					     self->hwpt_ids[1]);
1511 		test_cmd_mock_domain_replace(self->stdev_ids[0],
1512 					     self->hwpt_ids[1]);
1513 		test_cmd_mock_domain_replace(self->stdev_ids[0],
1514 					     self->hwpt_ids[0]);
1515 	}
1516 
1517 	test_cmd_mock_domain_replace(self->stdev_ids[0], self->ioas_id);
1518 	test_ioctl_destroy(ioas_id);
1519 }
1520 
1521 TEST_F(iommufd_mock_domain, alloc_hwpt)
1522 {
1523 	int i;
1524 
1525 	for (i = 0; i != variant->mock_domains; i++) {
1526 		uint32_t hwpt_id[2];
1527 		uint32_t stddev_id;
1528 
1529 		test_err_hwpt_alloc(EOPNOTSUPP,
1530 				    self->idev_ids[i], self->ioas_id,
1531 				    ~IOMMU_HWPT_ALLOC_NEST_PARENT, &hwpt_id[0]);
1532 		test_cmd_hwpt_alloc(self->idev_ids[i], self->ioas_id,
1533 				    0, &hwpt_id[0]);
1534 		test_cmd_hwpt_alloc(self->idev_ids[i], self->ioas_id,
1535 				    IOMMU_HWPT_ALLOC_NEST_PARENT, &hwpt_id[1]);
1536 
1537 		/* Do a hw_pagetable rotation test */
1538 		test_cmd_mock_domain_replace(self->stdev_ids[i], hwpt_id[0]);
1539 		EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, hwpt_id[0]));
1540 		test_cmd_mock_domain_replace(self->stdev_ids[i], hwpt_id[1]);
1541 		EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, hwpt_id[1]));
1542 		test_cmd_mock_domain_replace(self->stdev_ids[i], self->ioas_id);
1543 		test_ioctl_destroy(hwpt_id[1]);
1544 
1545 		test_cmd_mock_domain(hwpt_id[0], &stddev_id, NULL, NULL);
1546 		test_ioctl_destroy(stddev_id);
1547 		test_ioctl_destroy(hwpt_id[0]);
1548 	}
1549 }
1550 
1551 FIXTURE(iommufd_dirty_tracking)
1552 {
1553 	int fd;
1554 	uint32_t ioas_id;
1555 	uint32_t hwpt_id;
1556 	uint32_t stdev_id;
1557 	uint32_t idev_id;
1558 	unsigned long page_size;
1559 	unsigned long bitmap_size;
1560 	void *bitmap;
1561 	void *buffer;
1562 };
1563 
1564 FIXTURE_VARIANT(iommufd_dirty_tracking)
1565 {
1566 	unsigned long buffer_size;
1567 };
1568 
1569 FIXTURE_SETUP(iommufd_dirty_tracking)
1570 {
1571 	void *vrc;
1572 	int rc;
1573 
1574 	self->fd = open("/dev/iommu", O_RDWR);
1575 	ASSERT_NE(-1, self->fd);
1576 
1577 	rc = posix_memalign(&self->buffer, HUGEPAGE_SIZE, variant->buffer_size);
1578 	if (rc || !self->buffer) {
1579 		SKIP(return, "Skipping buffer_size=%lu due to errno=%d",
1580 			   variant->buffer_size, rc);
1581 	}
1582 
1583 	assert((uintptr_t)self->buffer % HUGEPAGE_SIZE == 0);
1584 	vrc = mmap(self->buffer, variant->buffer_size, PROT_READ | PROT_WRITE,
1585 		   MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
1586 	assert(vrc == self->buffer);
1587 
1588 	self->page_size = MOCK_PAGE_SIZE;
1589 	self->bitmap_size =
1590 		variant->buffer_size / self->page_size / BITS_PER_BYTE;
1591 
1592 	/* Provision with an extra (MOCK_PAGE_SIZE) for the unaligned case */
1593 	rc = posix_memalign(&self->bitmap, PAGE_SIZE,
1594 			    self->bitmap_size + MOCK_PAGE_SIZE);
1595 	assert(!rc);
1596 	assert(self->bitmap);
1597 	assert((uintptr_t)self->bitmap % PAGE_SIZE == 0);
1598 
1599 	test_ioctl_ioas_alloc(&self->ioas_id);
1600 	test_cmd_mock_domain(self->ioas_id, &self->stdev_id, &self->hwpt_id,
1601 			     &self->idev_id);
1602 }
1603 
1604 FIXTURE_TEARDOWN(iommufd_dirty_tracking)
1605 {
1606 	munmap(self->buffer, variant->buffer_size);
1607 	munmap(self->bitmap, self->bitmap_size);
1608 	teardown_iommufd(self->fd, _metadata);
1609 }
1610 
1611 FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty128k)
1612 {
1613 	/* one u32 index bitmap */
1614 	.buffer_size = 128UL * 1024UL,
1615 };
1616 
1617 FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty256k)
1618 {
1619 	/* one u64 index bitmap */
1620 	.buffer_size = 256UL * 1024UL,
1621 };
1622 
1623 FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty640k)
1624 {
1625 	/* two u64 index and trailing end bitmap */
1626 	.buffer_size = 640UL * 1024UL,
1627 };
1628 
1629 FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty128M)
1630 {
1631 	/* 4K bitmap (128M IOVA range) */
1632 	.buffer_size = 128UL * 1024UL * 1024UL,
1633 };
1634 
1635 FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty256M)
1636 {
1637 	/* 8K bitmap (256M IOVA range) */
1638 	.buffer_size = 256UL * 1024UL * 1024UL,
1639 };
1640 
1641 TEST_F(iommufd_dirty_tracking, enforce_dirty)
1642 {
1643 	uint32_t ioas_id, stddev_id, idev_id;
1644 	uint32_t hwpt_id, _hwpt_id;
1645 	uint32_t dev_flags;
1646 
1647 	/* Regular case */
1648 	dev_flags = MOCK_FLAGS_DEVICE_NO_DIRTY;
1649 	test_cmd_hwpt_alloc(self->idev_id, self->ioas_id,
1650 			    IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
1651 	test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
1652 	test_err_mock_domain_flags(EINVAL, hwpt_id, dev_flags, &stddev_id,
1653 				   NULL);
1654 	test_ioctl_destroy(stddev_id);
1655 	test_ioctl_destroy(hwpt_id);
1656 
1657 	/* IOMMU device does not support dirty tracking */
1658 	test_ioctl_ioas_alloc(&ioas_id);
1659 	test_cmd_mock_domain_flags(ioas_id, dev_flags, &stddev_id, &_hwpt_id,
1660 				   &idev_id);
1661 	test_err_hwpt_alloc(EOPNOTSUPP, idev_id, ioas_id,
1662 			    IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
1663 	test_ioctl_destroy(stddev_id);
1664 }
1665 
1666 TEST_F(iommufd_dirty_tracking, set_dirty_tracking)
1667 {
1668 	uint32_t stddev_id;
1669 	uint32_t hwpt_id;
1670 
1671 	test_cmd_hwpt_alloc(self->idev_id, self->ioas_id,
1672 			    IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
1673 	test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
1674 	test_cmd_set_dirty_tracking(hwpt_id, true);
1675 	test_cmd_set_dirty_tracking(hwpt_id, false);
1676 
1677 	test_ioctl_destroy(stddev_id);
1678 	test_ioctl_destroy(hwpt_id);
1679 }
1680 
1681 TEST_F(iommufd_dirty_tracking, device_dirty_capability)
1682 {
1683 	uint32_t caps = 0;
1684 	uint32_t stddev_id;
1685 	uint32_t hwpt_id;
1686 
1687 	test_cmd_hwpt_alloc(self->idev_id, self->ioas_id, 0, &hwpt_id);
1688 	test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
1689 	test_cmd_get_hw_capabilities(self->idev_id, caps,
1690 				     IOMMU_HW_CAP_DIRTY_TRACKING);
1691 	ASSERT_EQ(IOMMU_HW_CAP_DIRTY_TRACKING,
1692 		  caps & IOMMU_HW_CAP_DIRTY_TRACKING);
1693 
1694 	test_ioctl_destroy(stddev_id);
1695 	test_ioctl_destroy(hwpt_id);
1696 }
1697 
1698 TEST_F(iommufd_dirty_tracking, get_dirty_bitmap)
1699 {
1700 	uint32_t stddev_id;
1701 	uint32_t hwpt_id;
1702 	uint32_t ioas_id;
1703 
1704 	test_ioctl_ioas_alloc(&ioas_id);
1705 	test_ioctl_ioas_map_fixed_id(ioas_id, self->buffer,
1706 				     variant->buffer_size, MOCK_APERTURE_START);
1707 
1708 	test_cmd_hwpt_alloc(self->idev_id, ioas_id,
1709 			    IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
1710 	test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
1711 
1712 	test_cmd_set_dirty_tracking(hwpt_id, true);
1713 
1714 	test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
1715 				MOCK_APERTURE_START, self->page_size,
1716 				self->bitmap, self->bitmap_size, 0, _metadata);
1717 
1718 	/* PAGE_SIZE unaligned bitmap */
1719 	test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
1720 				MOCK_APERTURE_START, self->page_size,
1721 				self->bitmap + MOCK_PAGE_SIZE,
1722 				self->bitmap_size, 0, _metadata);
1723 
1724 	test_ioctl_destroy(stddev_id);
1725 	test_ioctl_destroy(hwpt_id);
1726 }
1727 
1728 TEST_F(iommufd_dirty_tracking, get_dirty_bitmap_no_clear)
1729 {
1730 	uint32_t stddev_id;
1731 	uint32_t hwpt_id;
1732 	uint32_t ioas_id;
1733 
1734 	test_ioctl_ioas_alloc(&ioas_id);
1735 	test_ioctl_ioas_map_fixed_id(ioas_id, self->buffer,
1736 				     variant->buffer_size, MOCK_APERTURE_START);
1737 
1738 	test_cmd_hwpt_alloc(self->idev_id, ioas_id,
1739 			    IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
1740 	test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
1741 
1742 	test_cmd_set_dirty_tracking(hwpt_id, true);
1743 
1744 	test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
1745 				MOCK_APERTURE_START, self->page_size,
1746 				self->bitmap, self->bitmap_size,
1747 				IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
1748 				_metadata);
1749 
1750 	/* Unaligned bitmap */
1751 	test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
1752 				MOCK_APERTURE_START, self->page_size,
1753 				self->bitmap + MOCK_PAGE_SIZE,
1754 				self->bitmap_size,
1755 				IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
1756 				_metadata);
1757 
1758 	test_ioctl_destroy(stddev_id);
1759 	test_ioctl_destroy(hwpt_id);
1760 }
1761 
1762 /* VFIO compatibility IOCTLs */
1763 
1764 TEST_F(iommufd, simple_ioctls)
1765 {
1766 	ASSERT_EQ(VFIO_API_VERSION, ioctl(self->fd, VFIO_GET_API_VERSION));
1767 	ASSERT_EQ(1, ioctl(self->fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU));
1768 }
1769 
1770 TEST_F(iommufd, unmap_cmd)
1771 {
1772 	struct vfio_iommu_type1_dma_unmap unmap_cmd = {
1773 		.iova = MOCK_APERTURE_START,
1774 		.size = PAGE_SIZE,
1775 	};
1776 
1777 	unmap_cmd.argsz = 1;
1778 	EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
1779 
1780 	unmap_cmd.argsz = sizeof(unmap_cmd);
1781 	unmap_cmd.flags = 1 << 31;
1782 	EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
1783 
1784 	unmap_cmd.flags = 0;
1785 	EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
1786 }
1787 
1788 TEST_F(iommufd, map_cmd)
1789 {
1790 	struct vfio_iommu_type1_dma_map map_cmd = {
1791 		.iova = MOCK_APERTURE_START,
1792 		.size = PAGE_SIZE,
1793 		.vaddr = (__u64)buffer,
1794 	};
1795 
1796 	map_cmd.argsz = 1;
1797 	EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
1798 
1799 	map_cmd.argsz = sizeof(map_cmd);
1800 	map_cmd.flags = 1 << 31;
1801 	EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
1802 
1803 	/* Requires a domain to be attached */
1804 	map_cmd.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
1805 	EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
1806 }
1807 
1808 TEST_F(iommufd, info_cmd)
1809 {
1810 	struct vfio_iommu_type1_info info_cmd = {};
1811 
1812 	/* Invalid argsz */
1813 	info_cmd.argsz = 1;
1814 	EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_GET_INFO, &info_cmd));
1815 
1816 	info_cmd.argsz = sizeof(info_cmd);
1817 	EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_IOMMU_GET_INFO, &info_cmd));
1818 }
1819 
1820 TEST_F(iommufd, set_iommu_cmd)
1821 {
1822 	/* Requires a domain to be attached */
1823 	EXPECT_ERRNO(ENODEV,
1824 		     ioctl(self->fd, VFIO_SET_IOMMU, VFIO_TYPE1v2_IOMMU));
1825 	EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU));
1826 }
1827 
1828 TEST_F(iommufd, vfio_ioas)
1829 {
1830 	struct iommu_vfio_ioas vfio_ioas_cmd = {
1831 		.size = sizeof(vfio_ioas_cmd),
1832 		.op = IOMMU_VFIO_IOAS_GET,
1833 	};
1834 	__u32 ioas_id;
1835 
1836 	/* ENODEV if there is no compat ioas */
1837 	EXPECT_ERRNO(ENODEV, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
1838 
1839 	/* Invalid id for set */
1840 	vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_SET;
1841 	EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
1842 
1843 	/* Valid id for set*/
1844 	test_ioctl_ioas_alloc(&ioas_id);
1845 	vfio_ioas_cmd.ioas_id = ioas_id;
1846 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
1847 
1848 	/* Same id comes back from get */
1849 	vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_GET;
1850 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
1851 	ASSERT_EQ(ioas_id, vfio_ioas_cmd.ioas_id);
1852 
1853 	/* Clear works */
1854 	vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_CLEAR;
1855 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
1856 	vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_GET;
1857 	EXPECT_ERRNO(ENODEV, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
1858 }
1859 
1860 FIXTURE(vfio_compat_mock_domain)
1861 {
1862 	int fd;
1863 	uint32_t ioas_id;
1864 };
1865 
1866 FIXTURE_VARIANT(vfio_compat_mock_domain)
1867 {
1868 	unsigned int version;
1869 };
1870 
1871 FIXTURE_SETUP(vfio_compat_mock_domain)
1872 {
1873 	struct iommu_vfio_ioas vfio_ioas_cmd = {
1874 		.size = sizeof(vfio_ioas_cmd),
1875 		.op = IOMMU_VFIO_IOAS_SET,
1876 	};
1877 
1878 	self->fd = open("/dev/iommu", O_RDWR);
1879 	ASSERT_NE(-1, self->fd);
1880 
1881 	/* Create what VFIO would consider a group */
1882 	test_ioctl_ioas_alloc(&self->ioas_id);
1883 	test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
1884 
1885 	/* Attach it to the vfio compat */
1886 	vfio_ioas_cmd.ioas_id = self->ioas_id;
1887 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
1888 	ASSERT_EQ(0, ioctl(self->fd, VFIO_SET_IOMMU, variant->version));
1889 }
1890 
1891 FIXTURE_TEARDOWN(vfio_compat_mock_domain)
1892 {
1893 	teardown_iommufd(self->fd, _metadata);
1894 }
1895 
1896 FIXTURE_VARIANT_ADD(vfio_compat_mock_domain, Ver1v2)
1897 {
1898 	.version = VFIO_TYPE1v2_IOMMU,
1899 };
1900 
1901 FIXTURE_VARIANT_ADD(vfio_compat_mock_domain, Ver1v0)
1902 {
1903 	.version = VFIO_TYPE1_IOMMU,
1904 };
1905 
1906 TEST_F(vfio_compat_mock_domain, simple_close)
1907 {
1908 }
1909 
1910 TEST_F(vfio_compat_mock_domain, option_huge_pages)
1911 {
1912 	struct iommu_option cmd = {
1913 		.size = sizeof(cmd),
1914 		.option_id = IOMMU_OPTION_HUGE_PAGES,
1915 		.op = IOMMU_OPTION_OP_GET,
1916 		.val64 = 3,
1917 		.object_id = self->ioas_id,
1918 	};
1919 
1920 	ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1921 	if (variant->version == VFIO_TYPE1_IOMMU) {
1922 		ASSERT_EQ(0, cmd.val64);
1923 	} else {
1924 		ASSERT_EQ(1, cmd.val64);
1925 	}
1926 }
1927 
1928 /*
1929  * Execute an ioctl command stored in buffer and check that the result does not
1930  * overflow memory.
1931  */
1932 static bool is_filled(const void *buf, uint8_t c, size_t len)
1933 {
1934 	const uint8_t *cbuf = buf;
1935 
1936 	for (; len; cbuf++, len--)
1937 		if (*cbuf != c)
1938 			return false;
1939 	return true;
1940 }
1941 
1942 #define ioctl_check_buf(fd, cmd)                                         \
1943 	({                                                               \
1944 		size_t _cmd_len = *(__u32 *)buffer;                      \
1945 									 \
1946 		memset(buffer + _cmd_len, 0xAA, BUFFER_SIZE - _cmd_len); \
1947 		ASSERT_EQ(0, ioctl(fd, cmd, buffer));                    \
1948 		ASSERT_EQ(true, is_filled(buffer + _cmd_len, 0xAA,       \
1949 					  BUFFER_SIZE - _cmd_len));      \
1950 	})
1951 
1952 static void check_vfio_info_cap_chain(struct __test_metadata *_metadata,
1953 				      struct vfio_iommu_type1_info *info_cmd)
1954 {
1955 	const struct vfio_info_cap_header *cap;
1956 
1957 	ASSERT_GE(info_cmd->argsz, info_cmd->cap_offset + sizeof(*cap));
1958 	cap = buffer + info_cmd->cap_offset;
1959 	while (true) {
1960 		size_t cap_size;
1961 
1962 		if (cap->next)
1963 			cap_size = (buffer + cap->next) - (void *)cap;
1964 		else
1965 			cap_size = (buffer + info_cmd->argsz) - (void *)cap;
1966 
1967 		switch (cap->id) {
1968 		case VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE: {
1969 			struct vfio_iommu_type1_info_cap_iova_range *data =
1970 				(void *)cap;
1971 
1972 			ASSERT_EQ(1, data->header.version);
1973 			ASSERT_EQ(1, data->nr_iovas);
1974 			EXPECT_EQ(MOCK_APERTURE_START,
1975 				  data->iova_ranges[0].start);
1976 			EXPECT_EQ(MOCK_APERTURE_LAST, data->iova_ranges[0].end);
1977 			break;
1978 		}
1979 		case VFIO_IOMMU_TYPE1_INFO_DMA_AVAIL: {
1980 			struct vfio_iommu_type1_info_dma_avail *data =
1981 				(void *)cap;
1982 
1983 			ASSERT_EQ(1, data->header.version);
1984 			ASSERT_EQ(sizeof(*data), cap_size);
1985 			break;
1986 		}
1987 		default:
1988 			ASSERT_EQ(false, true);
1989 			break;
1990 		}
1991 		if (!cap->next)
1992 			break;
1993 
1994 		ASSERT_GE(info_cmd->argsz, cap->next + sizeof(*cap));
1995 		ASSERT_GE(buffer + cap->next, (void *)cap);
1996 		cap = buffer + cap->next;
1997 	}
1998 }
1999 
2000 TEST_F(vfio_compat_mock_domain, get_info)
2001 {
2002 	struct vfio_iommu_type1_info *info_cmd = buffer;
2003 	unsigned int i;
2004 	size_t caplen;
2005 
2006 	/* Pre-cap ABI */
2007 	*info_cmd = (struct vfio_iommu_type1_info){
2008 		.argsz = offsetof(struct vfio_iommu_type1_info, cap_offset),
2009 	};
2010 	ioctl_check_buf(self->fd, VFIO_IOMMU_GET_INFO);
2011 	ASSERT_NE(0, info_cmd->iova_pgsizes);
2012 	ASSERT_EQ(VFIO_IOMMU_INFO_PGSIZES | VFIO_IOMMU_INFO_CAPS,
2013 		  info_cmd->flags);
2014 
2015 	/* Read the cap chain size */
2016 	*info_cmd = (struct vfio_iommu_type1_info){
2017 		.argsz = sizeof(*info_cmd),
2018 	};
2019 	ioctl_check_buf(self->fd, VFIO_IOMMU_GET_INFO);
2020 	ASSERT_NE(0, info_cmd->iova_pgsizes);
2021 	ASSERT_EQ(VFIO_IOMMU_INFO_PGSIZES | VFIO_IOMMU_INFO_CAPS,
2022 		  info_cmd->flags);
2023 	ASSERT_EQ(0, info_cmd->cap_offset);
2024 	ASSERT_LT(sizeof(*info_cmd), info_cmd->argsz);
2025 
2026 	/* Read the caps, kernel should never create a corrupted caps */
2027 	caplen = info_cmd->argsz;
2028 	for (i = sizeof(*info_cmd); i < caplen; i++) {
2029 		*info_cmd = (struct vfio_iommu_type1_info){
2030 			.argsz = i,
2031 		};
2032 		ioctl_check_buf(self->fd, VFIO_IOMMU_GET_INFO);
2033 		ASSERT_EQ(VFIO_IOMMU_INFO_PGSIZES | VFIO_IOMMU_INFO_CAPS,
2034 			  info_cmd->flags);
2035 		if (!info_cmd->cap_offset)
2036 			continue;
2037 		check_vfio_info_cap_chain(_metadata, info_cmd);
2038 	}
2039 }
2040 
2041 static void shuffle_array(unsigned long *array, size_t nelms)
2042 {
2043 	unsigned int i;
2044 
2045 	/* Shuffle */
2046 	for (i = 0; i != nelms; i++) {
2047 		unsigned long tmp = array[i];
2048 		unsigned int other = rand() % (nelms - i);
2049 
2050 		array[i] = array[other];
2051 		array[other] = tmp;
2052 	}
2053 }
2054 
2055 TEST_F(vfio_compat_mock_domain, map)
2056 {
2057 	struct vfio_iommu_type1_dma_map map_cmd = {
2058 		.argsz = sizeof(map_cmd),
2059 		.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
2060 		.vaddr = (uintptr_t)buffer,
2061 		.size = BUFFER_SIZE,
2062 		.iova = MOCK_APERTURE_START,
2063 	};
2064 	struct vfio_iommu_type1_dma_unmap unmap_cmd = {
2065 		.argsz = sizeof(unmap_cmd),
2066 		.size = BUFFER_SIZE,
2067 		.iova = MOCK_APERTURE_START,
2068 	};
2069 	unsigned long pages_iova[BUFFER_SIZE / PAGE_SIZE];
2070 	unsigned int i;
2071 
2072 	/* Simple map/unmap */
2073 	ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
2074 	ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
2075 	ASSERT_EQ(BUFFER_SIZE, unmap_cmd.size);
2076 
2077 	/* UNMAP_FLAG_ALL requires 0 iova/size */
2078 	ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
2079 	unmap_cmd.flags = VFIO_DMA_UNMAP_FLAG_ALL;
2080 	EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
2081 
2082 	unmap_cmd.iova = 0;
2083 	unmap_cmd.size = 0;
2084 	ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
2085 	ASSERT_EQ(BUFFER_SIZE, unmap_cmd.size);
2086 
2087 	/* Small pages */
2088 	for (i = 0; i != ARRAY_SIZE(pages_iova); i++) {
2089 		map_cmd.iova = pages_iova[i] =
2090 			MOCK_APERTURE_START + i * PAGE_SIZE;
2091 		map_cmd.vaddr = (uintptr_t)buffer + i * PAGE_SIZE;
2092 		map_cmd.size = PAGE_SIZE;
2093 		ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
2094 	}
2095 	shuffle_array(pages_iova, ARRAY_SIZE(pages_iova));
2096 
2097 	unmap_cmd.flags = 0;
2098 	unmap_cmd.size = PAGE_SIZE;
2099 	for (i = 0; i != ARRAY_SIZE(pages_iova); i++) {
2100 		unmap_cmd.iova = pages_iova[i];
2101 		ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
2102 	}
2103 }
2104 
2105 TEST_F(vfio_compat_mock_domain, huge_map)
2106 {
2107 	size_t buf_size = HUGEPAGE_SIZE * 2;
2108 	struct vfio_iommu_type1_dma_map map_cmd = {
2109 		.argsz = sizeof(map_cmd),
2110 		.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
2111 		.size = buf_size,
2112 		.iova = MOCK_APERTURE_START,
2113 	};
2114 	struct vfio_iommu_type1_dma_unmap unmap_cmd = {
2115 		.argsz = sizeof(unmap_cmd),
2116 	};
2117 	unsigned long pages_iova[16];
2118 	unsigned int i;
2119 	void *buf;
2120 
2121 	/* Test huge pages and splitting */
2122 	buf = mmap(0, buf_size, PROT_READ | PROT_WRITE,
2123 		   MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, -1,
2124 		   0);
2125 	ASSERT_NE(MAP_FAILED, buf);
2126 	map_cmd.vaddr = (uintptr_t)buf;
2127 	ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
2128 
2129 	unmap_cmd.size = buf_size / ARRAY_SIZE(pages_iova);
2130 	for (i = 0; i != ARRAY_SIZE(pages_iova); i++)
2131 		pages_iova[i] = MOCK_APERTURE_START + (i * unmap_cmd.size);
2132 	shuffle_array(pages_iova, ARRAY_SIZE(pages_iova));
2133 
2134 	/* type1 mode can cut up larger mappings, type1v2 always fails */
2135 	for (i = 0; i != ARRAY_SIZE(pages_iova); i++) {
2136 		unmap_cmd.iova = pages_iova[i];
2137 		unmap_cmd.size = buf_size / ARRAY_SIZE(pages_iova);
2138 		if (variant->version == VFIO_TYPE1_IOMMU) {
2139 			ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA,
2140 					   &unmap_cmd));
2141 		} else {
2142 			EXPECT_ERRNO(ENOENT,
2143 				     ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA,
2144 					   &unmap_cmd));
2145 		}
2146 	}
2147 }
2148 
2149 TEST_HARNESS_MAIN
2150