Skip to content

Commit 49ad127

Browse files
nicolincjgunthorpe
authored andcommitted
iommufd/selftest: Add vIOMMU coverage for IOMMU_HWPT_INVALIDATE ioctl
Add a viommu_cache test function to cover vIOMMU invalidations using the updated IOMMU_HWPT_INVALIDATE ioctl, which now allows passing in a vIOMMU via its hwpt_id field. Link: https://patch.msgid.link/r/f317f902041f3d05deaee4ca3fdd8ef4b8297361.1730836308.git.nicolinc@nvidia.com Reviewed-by: Kevin Tian <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Signed-off-by: Nicolin Chen <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 576ad6e commit 49ad127

File tree

2 files changed

+205
-0
lines changed

2 files changed

+205
-0
lines changed

tools/testing/selftests/iommu/iommufd.c

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2642,4 +2642,177 @@ TEST_F(iommufd_viommu, vdevice_alloc)
26422642
}
26432643
}
26442644

2645+
TEST_F(iommufd_viommu, vdevice_cache)
2646+
{
2647+
struct iommu_viommu_invalidate_selftest inv_reqs[2] = {};
2648+
uint32_t viommu_id = self->viommu_id;
2649+
uint32_t dev_id = self->device_id;
2650+
uint32_t vdev_id = 0;
2651+
uint32_t num_inv;
2652+
2653+
if (dev_id) {
2654+
test_cmd_vdevice_alloc(viommu_id, dev_id, 0x99, &vdev_id);
2655+
2656+
test_cmd_dev_check_cache_all(dev_id,
2657+
IOMMU_TEST_DEV_CACHE_DEFAULT);
2658+
2659+
/* Check data_type by passing zero-length array */
2660+
num_inv = 0;
2661+
test_cmd_viommu_invalidate(viommu_id, inv_reqs,
2662+
sizeof(*inv_reqs), &num_inv);
2663+
assert(!num_inv);
2664+
2665+
/* Negative test: Invalid data_type */
2666+
num_inv = 1;
2667+
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
2668+
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST_INVALID,
2669+
sizeof(*inv_reqs), &num_inv);
2670+
assert(!num_inv);
2671+
2672+
/* Negative test: structure size sanity */
2673+
num_inv = 1;
2674+
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
2675+
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
2676+
sizeof(*inv_reqs) + 1, &num_inv);
2677+
assert(!num_inv);
2678+
2679+
num_inv = 1;
2680+
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
2681+
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
2682+
1, &num_inv);
2683+
assert(!num_inv);
2684+
2685+
/* Negative test: invalid flag is passed */
2686+
num_inv = 1;
2687+
inv_reqs[0].flags = 0xffffffff;
2688+
inv_reqs[0].vdev_id = 0x99;
2689+
test_err_viommu_invalidate(EOPNOTSUPP, viommu_id, inv_reqs,
2690+
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
2691+
sizeof(*inv_reqs), &num_inv);
2692+
assert(!num_inv);
2693+
2694+
/* Negative test: invalid data_uptr when array is not empty */
2695+
num_inv = 1;
2696+
inv_reqs[0].flags = 0;
2697+
inv_reqs[0].vdev_id = 0x99;
2698+
test_err_viommu_invalidate(EINVAL, viommu_id, NULL,
2699+
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
2700+
sizeof(*inv_reqs), &num_inv);
2701+
assert(!num_inv);
2702+
2703+
/* Negative test: invalid entry_len when array is not empty */
2704+
num_inv = 1;
2705+
inv_reqs[0].flags = 0;
2706+
inv_reqs[0].vdev_id = 0x99;
2707+
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
2708+
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
2709+
0, &num_inv);
2710+
assert(!num_inv);
2711+
2712+
/* Negative test: invalid cache_id */
2713+
num_inv = 1;
2714+
inv_reqs[0].flags = 0;
2715+
inv_reqs[0].vdev_id = 0x99;
2716+
inv_reqs[0].cache_id = MOCK_DEV_CACHE_ID_MAX + 1;
2717+
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
2718+
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
2719+
sizeof(*inv_reqs), &num_inv);
2720+
assert(!num_inv);
2721+
2722+
/* Negative test: invalid vdev_id */
2723+
num_inv = 1;
2724+
inv_reqs[0].flags = 0;
2725+
inv_reqs[0].vdev_id = 0x9;
2726+
inv_reqs[0].cache_id = 0;
2727+
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
2728+
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
2729+
sizeof(*inv_reqs), &num_inv);
2730+
assert(!num_inv);
2731+
2732+
/*
2733+
* Invalidate the 1st cache entry but fail the 2nd request
2734+
* due to invalid flags configuration in the 2nd request.
2735+
*/
2736+
num_inv = 2;
2737+
inv_reqs[0].flags = 0;
2738+
inv_reqs[0].vdev_id = 0x99;
2739+
inv_reqs[0].cache_id = 0;
2740+
inv_reqs[1].flags = 0xffffffff;
2741+
inv_reqs[1].vdev_id = 0x99;
2742+
inv_reqs[1].cache_id = 1;
2743+
test_err_viommu_invalidate(EOPNOTSUPP, viommu_id, inv_reqs,
2744+
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
2745+
sizeof(*inv_reqs), &num_inv);
2746+
assert(num_inv == 1);
2747+
test_cmd_dev_check_cache(dev_id, 0, 0);
2748+
test_cmd_dev_check_cache(dev_id, 1,
2749+
IOMMU_TEST_DEV_CACHE_DEFAULT);
2750+
test_cmd_dev_check_cache(dev_id, 2,
2751+
IOMMU_TEST_DEV_CACHE_DEFAULT);
2752+
test_cmd_dev_check_cache(dev_id, 3,
2753+
IOMMU_TEST_DEV_CACHE_DEFAULT);
2754+
2755+
/*
2756+
* Invalidate the 1st cache entry but fail the 2nd request
2757+
* due to invalid cache_id configuration in the 2nd request.
2758+
*/
2759+
num_inv = 2;
2760+
inv_reqs[0].flags = 0;
2761+
inv_reqs[0].vdev_id = 0x99;
2762+
inv_reqs[0].cache_id = 0;
2763+
inv_reqs[1].flags = 0;
2764+
inv_reqs[1].vdev_id = 0x99;
2765+
inv_reqs[1].cache_id = MOCK_DEV_CACHE_ID_MAX + 1;
2766+
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
2767+
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
2768+
sizeof(*inv_reqs), &num_inv);
2769+
assert(num_inv == 1);
2770+
test_cmd_dev_check_cache(dev_id, 0, 0);
2771+
test_cmd_dev_check_cache(dev_id, 1,
2772+
IOMMU_TEST_DEV_CACHE_DEFAULT);
2773+
test_cmd_dev_check_cache(dev_id, 2,
2774+
IOMMU_TEST_DEV_CACHE_DEFAULT);
2775+
test_cmd_dev_check_cache(dev_id, 3,
2776+
IOMMU_TEST_DEV_CACHE_DEFAULT);
2777+
2778+
/* Invalidate the 2nd cache entry and verify */
2779+
num_inv = 1;
2780+
inv_reqs[0].flags = 0;
2781+
inv_reqs[0].vdev_id = 0x99;
2782+
inv_reqs[0].cache_id = 1;
2783+
test_cmd_viommu_invalidate(viommu_id, inv_reqs,
2784+
sizeof(*inv_reqs), &num_inv);
2785+
assert(num_inv == 1);
2786+
test_cmd_dev_check_cache(dev_id, 0, 0);
2787+
test_cmd_dev_check_cache(dev_id, 1, 0);
2788+
test_cmd_dev_check_cache(dev_id, 2,
2789+
IOMMU_TEST_DEV_CACHE_DEFAULT);
2790+
test_cmd_dev_check_cache(dev_id, 3,
2791+
IOMMU_TEST_DEV_CACHE_DEFAULT);
2792+
2793+
/* Invalidate the 3rd and 4th cache entries and verify */
2794+
num_inv = 2;
2795+
inv_reqs[0].flags = 0;
2796+
inv_reqs[0].vdev_id = 0x99;
2797+
inv_reqs[0].cache_id = 2;
2798+
inv_reqs[1].flags = 0;
2799+
inv_reqs[1].vdev_id = 0x99;
2800+
inv_reqs[1].cache_id = 3;
2801+
test_cmd_viommu_invalidate(viommu_id, inv_reqs,
2802+
sizeof(*inv_reqs), &num_inv);
2803+
assert(num_inv == 2);
2804+
test_cmd_dev_check_cache_all(dev_id, 0);
2805+
2806+
/* Invalidate all cache entries for nested_dev_id[1] and verify */
2807+
num_inv = 1;
2808+
inv_reqs[0].vdev_id = 0x99;
2809+
inv_reqs[0].flags = IOMMU_TEST_INVALIDATE_FLAG_ALL;
2810+
test_cmd_viommu_invalidate(viommu_id, inv_reqs,
2811+
sizeof(*inv_reqs), &num_inv);
2812+
assert(num_inv == 1);
2813+
test_cmd_dev_check_cache_all(dev_id, 0);
2814+
test_ioctl_destroy(vdev_id);
2815+
}
2816+
}
2817+
26452818
TEST_HARNESS_MAIN

tools/testing/selftests/iommu/iommufd_utils.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,38 @@ static int _test_cmd_hwpt_invalidate(int fd, __u32 hwpt_id, void *reqs,
305305
data_type, lreq, nreqs)); \
306306
})
307307

308+
static int _test_cmd_viommu_invalidate(int fd, __u32 viommu_id, void *reqs,
309+
uint32_t data_type, uint32_t lreq,
310+
uint32_t *nreqs)
311+
{
312+
struct iommu_hwpt_invalidate cmd = {
313+
.size = sizeof(cmd),
314+
.hwpt_id = viommu_id,
315+
.data_type = data_type,
316+
.data_uptr = (uint64_t)reqs,
317+
.entry_len = lreq,
318+
.entry_num = *nreqs,
319+
};
320+
int rc = ioctl(fd, IOMMU_HWPT_INVALIDATE, &cmd);
321+
*nreqs = cmd.entry_num;
322+
return rc;
323+
}
324+
325+
#define test_cmd_viommu_invalidate(viommu, reqs, lreq, nreqs) \
326+
({ \
327+
ASSERT_EQ(0, \
328+
_test_cmd_viommu_invalidate(self->fd, viommu, reqs, \
329+
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST, \
330+
lreq, nreqs)); \
331+
})
332+
#define test_err_viommu_invalidate(_errno, viommu_id, reqs, data_type, lreq, \
333+
nreqs) \
334+
({ \
335+
EXPECT_ERRNO(_errno, _test_cmd_viommu_invalidate( \
336+
self->fd, viommu_id, reqs, \
337+
data_type, lreq, nreqs)); \
338+
})
339+
308340
static int _test_cmd_access_replace_ioas(int fd, __u32 access_id,
309341
unsigned int ioas_id)
310342
{

0 commit comments

Comments
 (0)