@@ -22,6 +22,7 @@ enum {
IOMMU_TEST_OP_MOCK_DOMAIN_FLAGS,
IOMMU_TEST_OP_DIRTY,
IOMMU_TEST_OP_MD_CHECK_IOTLB,
+ IOMMU_TEST_OP_MV_CHECK_DEVID,
};
enum {
@@ -127,6 +128,10 @@ struct iommu_test_cmd {
__u32 id;
__u32 iotlb;
} check_iotlb;
+ struct {
+ __u32 idev_id;
+ __u32 dev_id;
+ } check_dev_id;
};
__u32 last;
};
@@ -999,6 +999,34 @@ static int iommufd_test_md_check_iotlb(struct iommufd_ucmd *ucmd,
return rc;
}
+static int iommufd_test_mv_check_dev_id(struct iommufd_ucmd *ucmd,
+ u32 viommu_id, unsigned int idev_id,
+ u32 dev_id)
+{
+ struct iommufd_device *idev;
+ struct mock_viommu *mv;
+ int rc = 0;
+
+ mv = container_of(iommufd_get_viommu(ucmd, viommu_id),
+ struct mock_viommu, core);
+ if (IS_ERR(mv))
+ return PTR_ERR(mv);
+
+ idev = iommufd_get_device(ucmd, idev_id);
+ if (IS_ERR(idev)) {
+ rc = PTR_ERR(idev);
+ goto out_put_viommu;
+ }
+
+ if (idev->dev != xa_load(&mv->ids, dev_id))
+ rc = -EINVAL;
+
+ iommufd_put_object(ucmd->ictx, &idev->obj);
+out_put_viommu:
+ iommufd_put_object(ucmd->ictx, &mv->core.obj);
+ return rc;
+}
+
struct selftest_access {
struct iommufd_access *access;
struct file *file;
@@ -1484,6 +1512,10 @@ int iommufd_test(struct iommufd_ucmd *ucmd)
return iommufd_test_md_check_iotlb(ucmd, cmd->id,
cmd->check_iotlb.id,
cmd->check_iotlb.iotlb);
+ case IOMMU_TEST_OP_MV_CHECK_DEVID:
+ return iommufd_test_mv_check_dev_id(ucmd, cmd->id,
+ cmd->check_dev_id.idev_id,
+ cmd->check_dev_id.dev_id);
case IOMMU_TEST_OP_CREATE_ACCESS:
return iommufd_test_create_access(ucmd, cmd->id,
cmd->create_access.flags);
@@ -288,14 +288,21 @@ TEST_F(iommufd_ioas, viommu)
test_err_viommu_set_dev_id(EINVAL, dev_id, viommu_id, 1ULL << 32);
test_cmd_viommu_set_dev_id(dev_id, viommu_id, 0x99);
test_err_viommu_set_dev_id(EBUSY, dev_id, viommu_id, 0x99);
+ test_cmd_viommu_check_dev_id(viommu_id, dev_id, 0x99);
test_cmd_mock_domain(self->ioas_id, &stdev2, &hwpt2, &device2);
test_err_viommu_set_dev_id(EBUSY, device2, viommu_id, 0x99);
test_cmd_viommu_set_dev_id(device2, viommu_id, 0xaa);
test_err_viommu_set_dev_id(EBUSY, device2, viommu_id, 0xaa);
+ test_cmd_viommu_check_dev_id(viommu_id, dev_id, 0x99);
+ test_cmd_viommu_check_dev_id(viommu_id, device2, 0xaa);
+
test_ioctl_destroy(stdev2);
+ test_cmd_viommu_check_dev_id(viommu_id, dev_id, 0x99);
+ test_err_viommu_check_dev_id(ENOENT, viommu_id, device2, 0xaa);
test_ioctl_destroy(viommu_id);
+ test_err_viommu_check_dev_id(ENOENT, viommu_id, dev_id, 0x99);
test_ioctl_destroy(hwpt_id);
} else {
test_err_viommu_alloc(ENOENT, dev_id, hwpt_id, &viommu_id);
@@ -731,3 +731,27 @@ static int _test_cmd_viommu_set_dev_id(int fd, __u32 device_id,
EXPECT_ERRNO(_errno, \
_test_cmd_viommu_set_dev_id(self->fd, device_id, \
viommu_id, virtual_id))
+
+static int _test_cmd_viommu_check_dev_id(int fd, __u32 viommu_id,
+ __u32 device_id, __u64 virtual_id)
+{
+ struct iommu_test_cmd test_cmd = {
+ .size = sizeof(test_cmd),
+ .op = IOMMU_TEST_OP_MV_CHECK_DEVID,
+ .id = viommu_id,
+ .check_dev_id = {
+ .idev_id = device_id,
+ .dev_id = virtual_id,
+ },
+ };
+ return ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_MV_CHECK_DEVID),
+ &test_cmd);
+}
+#define test_cmd_viommu_check_dev_id(viommu_id, device_id, expected) \
+ ASSERT_EQ(0, _test_cmd_viommu_check_dev_id(self->fd, viommu_id, \
+ device_id, expected))
+
+#define test_err_viommu_check_dev_id(_errno, viommu_id, device_id, expected) \
+ EXPECT_ERRNO(_errno, \
+ _test_cmd_viommu_check_dev_id(self->fd, viommu_id, \
+ device_id, expected))
This allows verifying the ids xarray of struct mock_viommu, and confirming the correctness of an IOMMU_VIOMMU_SET_DEV_ID call. Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> --- drivers/iommu/iommufd/iommufd_test.h | 5 +++ drivers/iommu/iommufd/selftest.c | 32 +++++++++++++++++++ tools/testing/selftests/iommu/iommufd.c | 7 ++++ tools/testing/selftests/iommu/iommufd_utils.h | 24 ++++++++++++++ 4 files changed, 68 insertions(+)