diff mbox series

[RFCv1,09/14] iommufd/selftest: Add IOMMU_VIOMMU_SET_DEV_ID test coverage

Message ID 80bd0cdd1108ff9247098b82a5b6bb0ea43c5ad1.1712978213.git.nicolinc@nvidia.com
State Handled Elsewhere
Headers show
Series Add Tegra241 (Grace) CMDQV Support (part 2/2) | expand

Commit Message

Nicolin Chen April 13, 2024, 3:47 a.m. UTC
Add an xarray to store the array of virtual ids to mock_devs, to cover the
new IOMMU_VIOMMU_SET_DEV_ID ioctl.

Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 drivers/iommu/iommufd/selftest.c              | 50 +++++++++++++++++++
 tools/testing/selftests/iommu/iommufd.c       | 14 ++++++
 tools/testing/selftests/iommu/iommufd_utils.h | 21 ++++++++
 3 files changed, 85 insertions(+)
diff mbox series

Patch

diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index e2fc2ec23093..4caed9304065 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -139,6 +139,7 @@  struct mock_dev {
 	struct device dev;
 	unsigned long flags;
 	int id;
+	unsigned int id_user;
 };
 
 struct selftest_obj {
@@ -516,6 +517,53 @@  static struct iommu_device *mock_probe_device(struct device *dev)
 
 struct mock_viommu {
 	struct iommufd_viommu core;
+	struct xarray ids;
+};
+
+static void mock_viommu_free(struct iommufd_viommu *viommu)
+{
+	struct mock_viommu *mv = container_of(viommu, struct mock_viommu, core);
+	struct device *dev;
+	unsigned long index;
+
+	xa_for_each(&mv->ids, index, dev)
+		xa_erase(&mv->ids, index);
+	xa_destroy(&mv->ids);
+}
+
+static int mock_viommu_set_dev_id(struct iommufd_viommu *viommu,
+				  struct device *dev, u64 dev_id)
+{
+	struct mock_viommu *mv = container_of(viommu, struct mock_viommu, core);
+	struct mock_dev *mdev = container_of(dev, struct mock_dev, dev);
+	u32 id = (u32)dev_id;
+	int rc;
+
+	if (dev_id > UINT_MAX)
+		return -EINVAL;
+	if (mdev->id_user > 0)
+		return -EBUSY;
+	rc = xa_alloc(&mv->ids, &id, dev, XA_LIMIT(id, id), GFP_KERNEL);
+	if (rc)
+		return rc;
+	mdev->id_user = (unsigned int)dev_id;
+	return 0;
+}
+
+static void mock_viommu_unset_dev_id(struct iommufd_viommu *viommu,
+				     struct device *dev)
+{
+	struct mock_viommu *mv = container_of(viommu, struct mock_viommu, core);
+	struct mock_dev *mdev = container_of(dev, struct mock_dev, dev);
+
+	WARN_ON(dev != xa_erase(&mv->ids, mdev->id_user));
+	mdev->id_user = 0;
+}
+
+static const struct iommufd_viommu_ops mock_viommu_ops = {
+	.free = mock_viommu_free,
+	.set_dev_id = mock_viommu_set_dev_id,
+	.unset_dev_id = mock_viommu_unset_dev_id,
 };
 
 static struct iommufd_viommu *mock_viommu_alloc(struct device *dev,
@@ -527,6 +575,8 @@  static struct iommufd_viommu *mock_viommu_alloc(struct device *dev,
 	mv = iommufd_viommu_alloc(mock_viommu, core);
 	if (!mv)
 		return ERR_PTR(-ENOMEM);
+	mv->core.ops = &mock_viommu_ops;
+	xa_init_flags(&mv->ids, XA_FLAGS_ALLOC1);
 
 	return &mv->core;
 }
diff --git a/tools/testing/selftests/iommu/iommufd.c b/tools/testing/selftests/iommu/iommufd.c
index dd7b7c7a06c6..378fbf00730e 100644
--- a/tools/testing/selftests/iommu/iommufd.c
+++ b/tools/testing/selftests/iommu/iommufd.c
@@ -271,6 +271,9 @@  TEST_F(iommufd_ioas, viommu)
 	uint32_t dev_id = self->device_id;
 	uint32_t viommu_id = 0;
 	uint32_t hwpt_id = 0;
+	uint32_t device2;
+	uint32_t stdev2;
+	uint32_t hwpt2;
 
 	if (dev_id) {
 		test_err_viommu_alloc(ENOENT, dev_id, hwpt_id, &viommu_id);
@@ -282,10 +285,21 @@  TEST_F(iommufd_ioas, viommu)
 				    IOMMU_HWPT_ALLOC_NEST_PARENT,
 				    &hwpt_id);
 		test_cmd_viommu_alloc(dev_id, hwpt_id, &viommu_id);
+		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_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_ioctl_destroy(stdev2);
+
 		test_ioctl_destroy(viommu_id);
 		test_ioctl_destroy(hwpt_id);
 	} else {
 		test_err_viommu_alloc(ENOENT, dev_id, hwpt_id, &viommu_id);
+		test_err_viommu_set_dev_id(ENOENT, dev_id, viommu_id, 99);
 	}
 }
 
diff --git a/tools/testing/selftests/iommu/iommufd_utils.h b/tools/testing/selftests/iommu/iommufd_utils.h
index 037c84189d50..81e9184fd1d5 100644
--- a/tools/testing/selftests/iommu/iommufd_utils.h
+++ b/tools/testing/selftests/iommu/iommufd_utils.h
@@ -710,3 +710,24 @@  static int _test_cmd_viommu_alloc(int fd, __u32 device_id, __u32 hwpt_id,
 #define test_err_viommu_alloc(_errno, device_id, hwpt_id, viommu_id)     \
 	EXPECT_ERRNO(_errno, _test_cmd_viommu_alloc(self->fd, device_id, \
 						    hwpt_id, 0, viommu_id))
+
+static int _test_cmd_viommu_set_dev_id(int fd, __u32 device_id,
+					__u32 viommu_id, __u64 virtual_id)
+{
+	struct iommu_viommu_set_dev_id cmd = {
+		.size = sizeof(cmd),
+		.dev_id = device_id,
+		.viommu_id = viommu_id,
+		.id = virtual_id,
+	};
+
+	return ioctl(fd, IOMMU_VIOMMU_SET_DEV_ID, &cmd);
+}
+
+#define test_cmd_viommu_set_dev_id(device_id, viommu_id, virtual_id)  \
+	ASSERT_EQ(0, _test_cmd_viommu_set_dev_id(self->fd, device_id, \
+						  viommu_id, virtual_id))
+#define test_err_viommu_set_dev_id(_errno, device_id, viommu_id, virtual_id) \
+	EXPECT_ERRNO(_errno,                                                 \
+		     _test_cmd_viommu_set_dev_id(self->fd, device_id,        \
+						  viommu_id, virtual_id))