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@xxxxxxxxxx> --- 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 --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)) -- 2.43.0