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