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