Jean-Philippe Brucker
2023-Sep-19 08:15 UTC
[PATCH v2 1/2] iommu/virtio: Make use of ops->iotlb_sync_map
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...)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. Once we merge domain_alloc() and finalize(), then this check disappears, but we still need to test nr_endpoints in map/unmap to handle detached domains (and we still need to fix the synchronization of nr_endpoints against attach/detach). That's why I preferred doing this on viommu and keeping it in one place. Thanks, Jean
Robin Murphy
2023-Sep-19 08:28 UTC
[PATCH v2 1/2] iommu/virtio: Make use of ops->iotlb_sync_map
On 2023-09-19 09:15, 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...) > > 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. > Once we merge domain_alloc() and finalize(), then this check disappears, > but we still need to test nr_endpoints in map/unmap to handle detached > domains (and we still need to fix the synchronization of nr_endpoints > against attach/detach). That's why I preferred doing this on viommu and > keeping it in one place.Fair enough - it just seems to me that in both cases it's a detached domain, so its previous history of whether it's ever been otherwise or not shouldn't matter. Even once viommu is initialised, does it really make sense to send sync commands for a mapping on a detached domain where we haven't actually sent any map/unmap commands? Thanks, Robin.
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