Message ID | 240dbfe0bec59b39e759d610485ff062054c370f.1728491453.git.nicolinc@nvidia.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | cover-letter: iommufd: Add vIOMMU infrastructure (Part-1) | expand |
On Wed, Oct 09, 2024 at 09:38:08AM -0700, Nicolin Chen wrote: > +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); What about the default viommu? What happens then? > + 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)) { It would be a bug if the iommu_dev being passed in was somehow released while iommufd had hold of it through vfio. So just use refcount_inc() Jason
On Thu, Oct 17, 2024 at 02:15:00PM -0300, Jason Gunthorpe wrote: > On Wed, Oct 09, 2024 at 09:38:08AM -0700, Nicolin Chen wrote: > > > +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); > > What about the default viommu? What happens then? IOMMU_VIOMMU_TYPE_DEFAULT is allocated by the core, it won't go down to iommu_ops->viommu_alloc (this function). > > + 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)) { > > It would be a bug if the iommu_dev being passed in was somehow > released while iommufd had hold of it through vfio. So just use > refcount_inc() OK. Thanks Nicolin
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,
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@nvidia.com> --- drivers/iommu/iommufd/iommufd_test.h | 2 ++ drivers/iommu/iommufd/selftest.c | 45 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+)