Skip to content

Commit bf26eb8

Browse files
nicolincjgunthorpe
authored andcommitted
iommufd/selftest: Add coverage for IOMMU_HWPT_INVALIDATE ioctl
Add test cases for the IOMMU_HWPT_INVALIDATE ioctl and verify it by using the new IOMMU_TEST_OP_MD_CHECK_IOTLB. Link: https://lore.kernel.org/r/20240111041015.47920-7-yi.l.liu@intel.com Reviewed-by: Kevin Tian <kevin.tian@intel.com> Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> Co-developed-by: Yi Liu <yi.l.liu@intel.com> Signed-off-by: Yi Liu <yi.l.liu@intel.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
1 parent e1fa664 commit bf26eb8

2 files changed

Lines changed: 179 additions & 0 deletions

File tree

tools/testing/selftests/iommu/iommufd.c

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ TEST_F(iommufd, cmd_length)
116116
TEST_LENGTH(iommu_destroy, IOMMU_DESTROY, id);
117117
TEST_LENGTH(iommu_hw_info, IOMMU_GET_HW_INFO, __reserved);
118118
TEST_LENGTH(iommu_hwpt_alloc, IOMMU_HWPT_ALLOC, __reserved);
119+
TEST_LENGTH(iommu_hwpt_invalidate, IOMMU_HWPT_INVALIDATE, __reserved);
119120
TEST_LENGTH(iommu_ioas_alloc, IOMMU_IOAS_ALLOC, out_ioas_id);
120121
TEST_LENGTH(iommu_ioas_iova_ranges, IOMMU_IOAS_IOVA_RANGES,
121122
out_iova_alignment);
@@ -271,7 +272,9 @@ TEST_F(iommufd_ioas, alloc_hwpt_nested)
271272
struct iommu_hwpt_selftest data = {
272273
.iotlb = IOMMU_TEST_IOTLB_DEFAULT,
273274
};
275+
struct iommu_hwpt_invalidate_selftest inv_reqs[2] = {};
274276
uint32_t nested_hwpt_id[2] = {};
277+
uint32_t num_inv;
275278
uint32_t parent_hwpt_id = 0;
276279
uint32_t parent_hwpt_id_not_work = 0;
277280
uint32_t test_hwpt_id = 0;
@@ -344,6 +347,151 @@ TEST_F(iommufd_ioas, alloc_hwpt_nested)
344347
EXPECT_ERRNO(EBUSY,
345348
_test_ioctl_destroy(self->fd, parent_hwpt_id));
346349

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+
347495
/* Attach device to nested_hwpt_id[0] that then will be busy */
348496
test_cmd_mock_domain_replace(self->stdev_id, nested_hwpt_id[0]);
349497
EXPECT_ERRNO(EBUSY,

tools/testing/selftests/iommu/iommufd_utils.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,37 @@ static int _test_cmd_hwpt_alloc(int fd, __u32 device_id, __u32 pt_id,
219219
test_cmd_hwpt_check_iotlb(hwpt_id, i, expected); \
220220
})
221221

222+
static int _test_cmd_hwpt_invalidate(int fd, __u32 hwpt_id, void *reqs,
223+
uint32_t data_type, uint32_t lreq,
224+
uint32_t *nreqs)
225+
{
226+
struct iommu_hwpt_invalidate cmd = {
227+
.size = sizeof(cmd),
228+
.hwpt_id = hwpt_id,
229+
.data_type = data_type,
230+
.data_uptr = (uint64_t)reqs,
231+
.entry_len = lreq,
232+
.entry_num = *nreqs,
233+
};
234+
int rc = ioctl(fd, IOMMU_HWPT_INVALIDATE, &cmd);
235+
*nreqs = cmd.entry_num;
236+
return rc;
237+
}
238+
239+
#define test_cmd_hwpt_invalidate(hwpt_id, reqs, data_type, lreq, nreqs) \
240+
({ \
241+
ASSERT_EQ(0, \
242+
_test_cmd_hwpt_invalidate(self->fd, hwpt_id, reqs, \
243+
data_type, lreq, nreqs)); \
244+
})
245+
#define test_err_hwpt_invalidate(_errno, hwpt_id, reqs, data_type, lreq, \
246+
nreqs) \
247+
({ \
248+
EXPECT_ERRNO(_errno, _test_cmd_hwpt_invalidate( \
249+
self->fd, hwpt_id, reqs, \
250+
data_type, lreq, nreqs)); \
251+
})
252+
222253
static int _test_cmd_access_replace_ioas(int fd, __u32 access_id,
223254
unsigned int ioas_id)
224255
{

0 commit comments

Comments
 (0)