mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 01:53:29 +02:00
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 <kevin.tian@intel.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
parent
576ad6eb45
commit
49ad127719
|
|
@ -2642,4 +2642,177 @@ TEST_F(iommufd_viommu, vdevice_alloc)
|
|||
}
|
||||
}
|
||||
|
||||
TEST_F(iommufd_viommu, vdevice_cache)
|
||||
{
|
||||
struct iommu_viommu_invalidate_selftest inv_reqs[2] = {};
|
||||
uint32_t viommu_id = self->viommu_id;
|
||||
uint32_t dev_id = self->device_id;
|
||||
uint32_t vdev_id = 0;
|
||||
uint32_t num_inv;
|
||||
|
||||
if (dev_id) {
|
||||
test_cmd_vdevice_alloc(viommu_id, dev_id, 0x99, &vdev_id);
|
||||
|
||||
test_cmd_dev_check_cache_all(dev_id,
|
||||
IOMMU_TEST_DEV_CACHE_DEFAULT);
|
||||
|
||||
/* Check data_type by passing zero-length array */
|
||||
num_inv = 0;
|
||||
test_cmd_viommu_invalidate(viommu_id, inv_reqs,
|
||||
sizeof(*inv_reqs), &num_inv);
|
||||
assert(!num_inv);
|
||||
|
||||
/* Negative test: Invalid data_type */
|
||||
num_inv = 1;
|
||||
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
|
||||
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST_INVALID,
|
||||
sizeof(*inv_reqs), &num_inv);
|
||||
assert(!num_inv);
|
||||
|
||||
/* Negative test: structure size sanity */
|
||||
num_inv = 1;
|
||||
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
|
||||
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
|
||||
sizeof(*inv_reqs) + 1, &num_inv);
|
||||
assert(!num_inv);
|
||||
|
||||
num_inv = 1;
|
||||
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
|
||||
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
|
||||
1, &num_inv);
|
||||
assert(!num_inv);
|
||||
|
||||
/* Negative test: invalid flag is passed */
|
||||
num_inv = 1;
|
||||
inv_reqs[0].flags = 0xffffffff;
|
||||
inv_reqs[0].vdev_id = 0x99;
|
||||
test_err_viommu_invalidate(EOPNOTSUPP, viommu_id, inv_reqs,
|
||||
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
|
||||
sizeof(*inv_reqs), &num_inv);
|
||||
assert(!num_inv);
|
||||
|
||||
/* Negative test: invalid data_uptr when array is not empty */
|
||||
num_inv = 1;
|
||||
inv_reqs[0].flags = 0;
|
||||
inv_reqs[0].vdev_id = 0x99;
|
||||
test_err_viommu_invalidate(EINVAL, viommu_id, NULL,
|
||||
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
|
||||
sizeof(*inv_reqs), &num_inv);
|
||||
assert(!num_inv);
|
||||
|
||||
/* Negative test: invalid entry_len when array is not empty */
|
||||
num_inv = 1;
|
||||
inv_reqs[0].flags = 0;
|
||||
inv_reqs[0].vdev_id = 0x99;
|
||||
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
|
||||
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
|
||||
0, &num_inv);
|
||||
assert(!num_inv);
|
||||
|
||||
/* Negative test: invalid cache_id */
|
||||
num_inv = 1;
|
||||
inv_reqs[0].flags = 0;
|
||||
inv_reqs[0].vdev_id = 0x99;
|
||||
inv_reqs[0].cache_id = MOCK_DEV_CACHE_ID_MAX + 1;
|
||||
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
|
||||
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
|
||||
sizeof(*inv_reqs), &num_inv);
|
||||
assert(!num_inv);
|
||||
|
||||
/* Negative test: invalid vdev_id */
|
||||
num_inv = 1;
|
||||
inv_reqs[0].flags = 0;
|
||||
inv_reqs[0].vdev_id = 0x9;
|
||||
inv_reqs[0].cache_id = 0;
|
||||
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
|
||||
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
|
||||
sizeof(*inv_reqs), &num_inv);
|
||||
assert(!num_inv);
|
||||
|
||||
/*
|
||||
* Invalidate the 1st cache entry but fail the 2nd request
|
||||
* due to invalid flags configuration in the 2nd request.
|
||||
*/
|
||||
num_inv = 2;
|
||||
inv_reqs[0].flags = 0;
|
||||
inv_reqs[0].vdev_id = 0x99;
|
||||
inv_reqs[0].cache_id = 0;
|
||||
inv_reqs[1].flags = 0xffffffff;
|
||||
inv_reqs[1].vdev_id = 0x99;
|
||||
inv_reqs[1].cache_id = 1;
|
||||
test_err_viommu_invalidate(EOPNOTSUPP, viommu_id, inv_reqs,
|
||||
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
|
||||
sizeof(*inv_reqs), &num_inv);
|
||||
assert(num_inv == 1);
|
||||
test_cmd_dev_check_cache(dev_id, 0, 0);
|
||||
test_cmd_dev_check_cache(dev_id, 1,
|
||||
IOMMU_TEST_DEV_CACHE_DEFAULT);
|
||||
test_cmd_dev_check_cache(dev_id, 2,
|
||||
IOMMU_TEST_DEV_CACHE_DEFAULT);
|
||||
test_cmd_dev_check_cache(dev_id, 3,
|
||||
IOMMU_TEST_DEV_CACHE_DEFAULT);
|
||||
|
||||
/*
|
||||
* Invalidate the 1st cache entry but fail the 2nd request
|
||||
* due to invalid cache_id configuration in the 2nd request.
|
||||
*/
|
||||
num_inv = 2;
|
||||
inv_reqs[0].flags = 0;
|
||||
inv_reqs[0].vdev_id = 0x99;
|
||||
inv_reqs[0].cache_id = 0;
|
||||
inv_reqs[1].flags = 0;
|
||||
inv_reqs[1].vdev_id = 0x99;
|
||||
inv_reqs[1].cache_id = MOCK_DEV_CACHE_ID_MAX + 1;
|
||||
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
|
||||
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
|
||||
sizeof(*inv_reqs), &num_inv);
|
||||
assert(num_inv == 1);
|
||||
test_cmd_dev_check_cache(dev_id, 0, 0);
|
||||
test_cmd_dev_check_cache(dev_id, 1,
|
||||
IOMMU_TEST_DEV_CACHE_DEFAULT);
|
||||
test_cmd_dev_check_cache(dev_id, 2,
|
||||
IOMMU_TEST_DEV_CACHE_DEFAULT);
|
||||
test_cmd_dev_check_cache(dev_id, 3,
|
||||
IOMMU_TEST_DEV_CACHE_DEFAULT);
|
||||
|
||||
/* Invalidate the 2nd cache entry and verify */
|
||||
num_inv = 1;
|
||||
inv_reqs[0].flags = 0;
|
||||
inv_reqs[0].vdev_id = 0x99;
|
||||
inv_reqs[0].cache_id = 1;
|
||||
test_cmd_viommu_invalidate(viommu_id, inv_reqs,
|
||||
sizeof(*inv_reqs), &num_inv);
|
||||
assert(num_inv == 1);
|
||||
test_cmd_dev_check_cache(dev_id, 0, 0);
|
||||
test_cmd_dev_check_cache(dev_id, 1, 0);
|
||||
test_cmd_dev_check_cache(dev_id, 2,
|
||||
IOMMU_TEST_DEV_CACHE_DEFAULT);
|
||||
test_cmd_dev_check_cache(dev_id, 3,
|
||||
IOMMU_TEST_DEV_CACHE_DEFAULT);
|
||||
|
||||
/* Invalidate the 3rd and 4th cache entries and verify */
|
||||
num_inv = 2;
|
||||
inv_reqs[0].flags = 0;
|
||||
inv_reqs[0].vdev_id = 0x99;
|
||||
inv_reqs[0].cache_id = 2;
|
||||
inv_reqs[1].flags = 0;
|
||||
inv_reqs[1].vdev_id = 0x99;
|
||||
inv_reqs[1].cache_id = 3;
|
||||
test_cmd_viommu_invalidate(viommu_id, inv_reqs,
|
||||
sizeof(*inv_reqs), &num_inv);
|
||||
assert(num_inv == 2);
|
||||
test_cmd_dev_check_cache_all(dev_id, 0);
|
||||
|
||||
/* Invalidate all cache entries for nested_dev_id[1] and verify */
|
||||
num_inv = 1;
|
||||
inv_reqs[0].vdev_id = 0x99;
|
||||
inv_reqs[0].flags = IOMMU_TEST_INVALIDATE_FLAG_ALL;
|
||||
test_cmd_viommu_invalidate(viommu_id, inv_reqs,
|
||||
sizeof(*inv_reqs), &num_inv);
|
||||
assert(num_inv == 1);
|
||||
test_cmd_dev_check_cache_all(dev_id, 0);
|
||||
test_ioctl_destroy(vdev_id);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_HARNESS_MAIN
|
||||
|
|
|
|||
|
|
@ -305,6 +305,38 @@ static int _test_cmd_hwpt_invalidate(int fd, __u32 hwpt_id, void *reqs,
|
|||
data_type, lreq, nreqs)); \
|
||||
})
|
||||
|
||||
static int _test_cmd_viommu_invalidate(int fd, __u32 viommu_id, void *reqs,
|
||||
uint32_t data_type, uint32_t lreq,
|
||||
uint32_t *nreqs)
|
||||
{
|
||||
struct iommu_hwpt_invalidate cmd = {
|
||||
.size = sizeof(cmd),
|
||||
.hwpt_id = viommu_id,
|
||||
.data_type = data_type,
|
||||
.data_uptr = (uint64_t)reqs,
|
||||
.entry_len = lreq,
|
||||
.entry_num = *nreqs,
|
||||
};
|
||||
int rc = ioctl(fd, IOMMU_HWPT_INVALIDATE, &cmd);
|
||||
*nreqs = cmd.entry_num;
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define test_cmd_viommu_invalidate(viommu, reqs, lreq, nreqs) \
|
||||
({ \
|
||||
ASSERT_EQ(0, \
|
||||
_test_cmd_viommu_invalidate(self->fd, viommu, reqs, \
|
||||
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST, \
|
||||
lreq, nreqs)); \
|
||||
})
|
||||
#define test_err_viommu_invalidate(_errno, viommu_id, reqs, data_type, lreq, \
|
||||
nreqs) \
|
||||
({ \
|
||||
EXPECT_ERRNO(_errno, _test_cmd_viommu_invalidate( \
|
||||
self->fd, viommu_id, reqs, \
|
||||
data_type, lreq, nreqs)); \
|
||||
})
|
||||
|
||||
static int _test_cmd_access_replace_ioas(int fd, __u32 access_id,
|
||||
unsigned int ioas_id)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user