Implement the viommu alloc/free functions to increase/reduce refcount of its dependent mock iommu device. User space can verify this loop via the IOMMU_VIOMMU_TYPE_SELFTEST. Signed-off-by: Nicolin Chen <nicolinc@xxxxxxxxxx> --- drivers/iommu/iommufd/iommufd_test.h | 2 ++ drivers/iommu/iommufd/selftest.c | 45 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/drivers/iommu/iommufd/iommufd_test.h b/drivers/iommu/iommufd/iommufd_test.h index f4bc23a92f9a..edced4ac7cd3 100644 --- a/drivers/iommu/iommufd/iommufd_test.h +++ b/drivers/iommu/iommufd/iommufd_test.h @@ -180,4 +180,6 @@ struct iommu_hwpt_invalidate_selftest { __u32 iotlb_id; }; +#define IOMMU_VIOMMU_TYPE_SELFTEST 0xdeadbeef + #endif diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c index a89a865617db..4fcf475facb1 100644 --- a/drivers/iommu/iommufd/selftest.c +++ b/drivers/iommu/iommufd/selftest.c @@ -132,6 +132,10 @@ struct mock_iommu_domain_nested { u32 iotlb[MOCK_NESTED_DOMAIN_IOTLB_NUM]; }; +struct mock_viommu { + struct iommufd_viommu core; +}; + enum selftest_obj_type { TYPE_IDEV, }; @@ -544,6 +548,46 @@ static int mock_dev_disable_feat(struct device *dev, enum iommu_dev_features fea return 0; } +static void mock_viommu_free(struct iommufd_viommu *viommu) +{ + struct mock_iommu_device *mock_iommu = + container_of(viommu->iommu_dev, struct mock_iommu_device, + iommu_dev); + + if (refcount_dec_and_test(&mock_iommu->users)) + wake_up_interruptible_all(&mock_iommu->wait); + + /* iommufd core frees mock_viommu and viommu */ +} + +static struct iommufd_viommu_ops mock_viommu_ops = { + .free = mock_viommu_free, +}; + +static struct iommufd_viommu * +mock_viommu_alloc(struct iommu_device *iommu_dev, struct iommu_domain *domain, + struct iommufd_ctx *ictx, unsigned int viommu_type) +{ + struct mock_iommu_device *mock_iommu = + container_of(iommu_dev, struct mock_iommu_device, iommu_dev); + struct mock_viommu *mock_viommu; + + if (viommu_type != IOMMU_VIOMMU_TYPE_SELFTEST) + return ERR_PTR(-EOPNOTSUPP); + + mock_viommu = iommufd_viommu_alloc(ictx, mock_viommu, core, + &mock_viommu_ops); + if (IS_ERR(mock_viommu)) + return ERR_CAST(mock_viommu); + + if (!refcount_inc_not_zero(&mock_iommu->users)) { + kfree(mock_viommu); + return ERR_PTR(-ENXIO); + } + + return &mock_viommu->core; +} + static const struct iommu_ops mock_ops = { /* * IOMMU_DOMAIN_BLOCKED cannot be returned from def_domain_type() @@ -563,6 +607,7 @@ static const struct iommu_ops mock_ops = { .dev_enable_feat = mock_dev_enable_feat, .dev_disable_feat = mock_dev_disable_feat, .user_pasid_table = true, + .viommu_alloc = mock_viommu_alloc, .default_domain_ops = &(struct iommu_domain_ops){ .free = mock_domain_free, -- 2.43.0