Jason Gunthorpe
2023-Sep-19 14:46 UTC
[PATCH v2 1/2] iommu/virtio: Make use of ops->iotlb_sync_map
On Tue, Sep 19, 2023 at 09:15:19AM +0100, Jean-Philippe Brucker wrote:> On Mon, Sep 18, 2023 at 05:37:47PM +0100, Robin Murphy wrote: > > > diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c > > > index 17dcd826f5c2..3649586f0e5c 100644 > > > --- a/drivers/iommu/virtio-iommu.c > > > +++ b/drivers/iommu/virtio-iommu.c > > > @@ -189,6 +189,12 @@ static int viommu_sync_req(struct viommu_dev *viommu) > > > int ret; > > > unsigned long flags; > > > + /* > > > + * .iotlb_sync_map and .flush_iotlb_all may be called before the viommu > > > + * is initialized e.g. via iommu_create_device_direct_mappings() > > > + */ > > > + if (!viommu) > > > + return 0; > > > > Minor nit: I'd be inclined to make that check explicitly in the places where > > it definitely is expected, rather than allowing *any* sync to silently do > > nothing if called incorrectly. Plus then they could use > > vdomain->nr_endpoints for consistency with the equivalent checks elsewhere > > (it did take me a moment to figure out how we could get to .iotlb_sync_map > > with a NULL viommu without viommu_map_pages() blowing up first...)This makes more sense to me Ultimately this driver should reach a point where every iommu_domain always has a non-null domain->viommu because it will be set during alloc. But it can still have nr_endpoints == 0, doesn't it make sense to avoid sync in this case? (btw this driver is missing locking around vdomain->nr_endpoints)> They're not strictly equivalent: this check works around a temporary issue > with the IOMMU core, which calls map/unmap before the domain is > finalized.Where? The above points to iommu_create_device_direct_mappings() but it doesn't because the pgsize_bitmap == 0: static int iommu_create_device_direct_mappings(struct iommu_domain *domain, struct device *dev) { struct iommu_resv_region *entry; struct list_head mappings; unsigned long pg_size; int ret = 0; pg_size = domain->pgsize_bitmap ? 1UL << __ffs(domain->pgsize_bitmap) : 0; INIT_LIST_HEAD(&mappings); if (WARN_ON_ONCE(iommu_is_dma_domain(domain) && !pg_size)) Indeed, the driver should be failing all map's until the domain is finalized because it has no way to check the IOVA matches the eventual aperture. Jason
Jean-Philippe Brucker
2023-Sep-22 07:57 UTC
[PATCH v2 1/2] iommu/virtio: Make use of ops->iotlb_sync_map
On Tue, Sep 19, 2023 at 11:46:49AM -0300, Jason Gunthorpe wrote:> On Tue, Sep 19, 2023 at 09:15:19AM +0100, Jean-Philippe Brucker wrote: > > On Mon, Sep 18, 2023 at 05:37:47PM +0100, Robin Murphy wrote: > > > > diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c > > > > index 17dcd826f5c2..3649586f0e5c 100644 > > > > --- a/drivers/iommu/virtio-iommu.c > > > > +++ b/drivers/iommu/virtio-iommu.c > > > > @@ -189,6 +189,12 @@ static int viommu_sync_req(struct viommu_dev *viommu) > > > > int ret; > > > > unsigned long flags; > > > > + /* > > > > + * .iotlb_sync_map and .flush_iotlb_all may be called before the viommu > > > > + * is initialized e.g. via iommu_create_device_direct_mappings() > > > > + */ > > > > + if (!viommu) > > > > + return 0; > > > > > > Minor nit: I'd be inclined to make that check explicitly in the places where > > > it definitely is expected, rather than allowing *any* sync to silently do > > > nothing if called incorrectly. Plus then they could use > > > vdomain->nr_endpoints for consistency with the equivalent checks elsewhere > > > (it did take me a moment to figure out how we could get to .iotlb_sync_map > > > with a NULL viommu without viommu_map_pages() blowing up first...) > > This makes more sense to me > > Ultimately this driver should reach a point where every iommu_domain > always has a non-null domain->viommu because it will be set during > alloc. > > But it can still have nr_endpoints == 0, doesn't it make sense to > avoid sync in this case? > > (btw this driver is missing locking around vdomain->nr_endpoints)Yes, that's on my list> > > They're not strictly equivalent: this check works around a temporary issue > > with the IOMMU core, which calls map/unmap before the domain is > > finalized. > > Where? The above points to iommu_create_device_direct_mappings() but > it doesn't because the pgsize_bitmap == 0:__iommu_domain_alloc() sets pgsize_bitmap in this case: /* * If not already set, assume all sizes by default; the driver * may override this later */ if (!domain->pgsize_bitmap) domain->pgsize_bitmap = bus->iommu_ops->pgsize_bitmap; Thanks, Jean