Re: [PATCH 2/5] iommu: Add blocking_domain_ops field in iommu_ops
On 2022/5/20 16:45, Joerg Roedel wrote: On Mon, May 16, 2022 at 09:57:56AM +0800, Lu Baolu wrote: const struct iommu_domain_ops *default_domain_ops; + const struct iommu_domain_ops *blocking_domain_ops; I don't understand why extra domain-ops are needed for this. I think it would be more straight-forward to implement allocation of IOMMU_DOMAIN_BLOCKED domains in each driver and let the details be handled in the set_dev() call-back. The IOMMU driver can make sure DMA is blocked for a device when it encounters a IOMMU_DOMAIN_BLOCKED domain. For IOMMUs that have no explicit way to block DMA could just use an unmanaged domain with an empty page-table. Yes, this is what will go. Best regards, baolu ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/5] iommu: Add blocking_domain_ops field in iommu_ops
On Mon, May 16, 2022 at 09:57:56AM +0800, Lu Baolu wrote: > const struct iommu_domain_ops *default_domain_ops; > + const struct iommu_domain_ops *blocking_domain_ops; I don't understand why extra domain-ops are needed for this. I think it would be more straight-forward to implement allocation of IOMMU_DOMAIN_BLOCKED domains in each driver and let the details be handled in the set_dev() call-back. The IOMMU driver can make sure DMA is blocked for a device when it encounters a IOMMU_DOMAIN_BLOCKED domain. For IOMMUs that have no explicit way to block DMA could just use an unmanaged domain with an empty page-table. Regards, Joerg ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/5] iommu: Add blocking_domain_ops field in iommu_ops
On 2022/5/17 21:13, Jason Gunthorpe wrote: On Tue, May 17, 2022 at 01:43:03PM +0100, Robin Murphy wrote: FWIW from my point of view I'm happy with having a .detach_dev_pasid op meaning implicitly-blocked access for now. If this is the path then lets not call it attach/detach please. 'set_dev_pasid' and 'set_dev_blocking_pasid' are clearer names. Sure. And with the blocking domain implemented, the set_dev_blocking_pasid could be deprecated. On SMMUv3, PASIDs don't mix with our current notion of IOMMU_DOMAIN_IDENTITY (nor the potential one for IOMMU_DOMAIN_BLOCKED), so giving PASIDs functional symmetry with devices would need significantly more work anyway. There is no extra work in the driver, beyond SMMU having to implement a blocking domain. The blocking domain's set_dev_pasid op simply is whatever set_dev_blocking_pasid would have done on the unmanaged domain. identity doesn't come into this, identity domains should have a NULL set_dev_pasid op if the driver can't support using it on a PASID. IMHO blocking_domain->ops->set_dev_pasid() is just a more logical name than domain->ops->set_dev_blocking_pasid() - especially since VFIO would like drivers to implement blocking domain anyhow. Perhaps implementing blocking domains for intel and smmuv3 iommu drivers seem to be a more practical start. Best regards, baolu ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/5] iommu: Add blocking_domain_ops field in iommu_ops
On Tue, May 17, 2022 at 01:43:03PM +0100, Robin Murphy wrote: > FWIW from my point of view I'm happy with having a .detach_dev_pasid op > meaning implicitly-blocked access for now. If this is the path then lets not call it attach/detach please. 'set_dev_pasid' and 'set_dev_blocking_pasid' are clearer names. > On SMMUv3, PASIDs don't mix with our current notion of > IOMMU_DOMAIN_IDENTITY (nor the potential one for > IOMMU_DOMAIN_BLOCKED), so giving PASIDs functional symmetry with > devices would need significantly more work anyway. There is no extra work in the driver, beyond SMMU having to implement a blocking domain. The blocking domain's set_dev_pasid op simply is whatever set_dev_blocking_pasid would have done on the unmanaged domain. identity doesn't come into this, identity domains should have a NULL set_dev_pasid op if the driver can't support using it on a PASID. IMHO blocking_domain->ops->set_dev_pasid() is just a more logical name than domain->ops->set_dev_blocking_pasid() - especially since VFIO would like drivers to implement blocking domain anyhow. Jason ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/5] iommu: Add blocking_domain_ops field in iommu_ops
On Tue, May 17, 2022 at 10:37:55AM +0800, Baolu Lu wrote: > Hi Jason, > > On 2022/5/16 21:57, Jason Gunthorpe wrote: > > On Mon, May 16, 2022 at 12:22:08PM +0100, Robin Murphy wrote: > > > On 2022-05-16 02:57, Lu Baolu wrote: > > > > Each IOMMU driver must provide a blocking domain ops. If the hardware > > > > supports detaching domain from device, setting blocking domain equals > > > > detaching the existing domain from the deivce. Otherwise, an UNMANAGED > > > > domain without any mapping will be used instead. > > > Unfortunately that's backwards - most of the implementations of > > > .detach_dev > > > are disabling translation entirely, meaning the device ends up effectively > > > in passthrough rather than blocked. > > Ideally we'd convert the detach_dev of every driver into either > > a blocking or identity domain. The trick is knowing which is which.. > > I am still a bit puzzled about how the blocking_domain should be used when > it is extended to support ->set_dev_pasid. > > If it's a blocking domain, the IOMMU driver knows that setting the > blocking domain to device pasid means detaching the existing one. > But if it's an identity domain, how could the IOMMU driver choose > between: The identity domain would never be used for detaching a PASID. The reason it is in this explanation is because every detach_dev op should be deleted - and the code that it was doing can remain in the driver as either a blocking or identity domain. > > So, the approach here should be to go driver by driver and convert > > detach_dev to either identity, blocking or just delete it entirely, > > excluding the above 7 that don't support default domains. And get acks > > from the driver owners. > Agreed. There seems to be a long way to go. I am wondering if we could > decouple this refactoring from my new SVA API work? We can easily switch > .detach_dev_pasid to using blocking domain later. Well, PASID has nothing to do with this. PASID enabled drivers would just need: - Must be using default domains and must have a NULL detach_dev op - Must provide a blocking_domain - Must provide set_dev_pasid for the unmanaged and blocking domains it creates That is it. Realigning the existing drivers for their base RID support is another task. The appeal of this is that it matches how base RID support should look and doesn't continue the confusing appearance that there is a strictly paired attach/detach operation. Any domain can be set ony and RID/PASID at any time. Drivers intended to be used with VFIO really want a blocking_domain anyhow for efficiency. Jason ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/5] iommu: Add blocking_domain_ops field in iommu_ops
On 2022-05-17 03:37, Baolu Lu wrote: Hi Jason, On 2022/5/16 21:57, Jason Gunthorpe wrote: On Mon, May 16, 2022 at 12:22:08PM +0100, Robin Murphy wrote: On 2022-05-16 02:57, Lu Baolu wrote: Each IOMMU driver must provide a blocking domain ops. If the hardware supports detaching domain from device, setting blocking domain equals detaching the existing domain from the deivce. Otherwise, an UNMANAGED domain without any mapping will be used instead. Unfortunately that's backwards - most of the implementations of .detach_dev are disabling translation entirely, meaning the device ends up effectively in passthrough rather than blocked. Ideally we'd convert the detach_dev of every driver into either a blocking or identity domain. The trick is knowing which is which.. I am still a bit puzzled about how the blocking_domain should be used when it is extended to support ->set_dev_pasid. If it's a blocking domain, the IOMMU driver knows that setting the blocking domain to device pasid means detaching the existing one. But if it's an identity domain, how could the IOMMU driver choose between: - setting the input domain to the pasid on device; or, - detaching the existing domain. I've ever thought about below solutions: - Checking the domain types and dispatching them to different operations. - Using different blocking domains for different types of domains. But both look rough. Guessing going down the list: apple dart - blocking, detach_dev calls apple_dart_hw_disable_dma() same as IOMMU_DOMAIN_BLOCKED [I wonder if this drive ris wrong in other ways though because I dont see a remove_streams in attach_dev] exynos - this seems to disable the 'sysmmu' so I'm guessing this is identity iommu-vmsa - Comment says 'disable mmu translaction' so I'm guessing this is idenity mkt_v1 - Code looks similar to mkt, which is probably identity. rkt - No idea sprd - No idea sun50i - This driver confusingly treats identity the same as unmanaged, seems wrong, no idea. amd - Not sure, clear_dte_entry() seems to set translation on but points the PTE to 0 ? Based on the spec table 8 I would have expected TV to be clear which would be blocking. Maybe a bug?? arm smmu qcomm - not sure intel - blocking These doesn't support default domains, so detach_dev should return back to DMA API ownership, which is either identity or something weird: fsl_pamu - identity due to the PPC use of dma direct msm mkt omap s390 - platform DMA ops terga-gart - Usually something called a GART would be 0 length once disabled, guessing blocking? tegra-smmu So, the approach here should be to go driver by driver and convert detach_dev to either identity, blocking or just delete it entirely, excluding the above 7 that don't support default domains. And get acks from the driver owners. Agreed. There seems to be a long way to go. I am wondering if we could decouple this refactoring from my new SVA API work? We can easily switch .detach_dev_pasid to using blocking domain later. FWIW from my point of view I'm happy with having a .detach_dev_pasid op meaning implicitly-blocked access for now. On SMMUv3, PASIDs don't mix with our current notion of IOMMU_DOMAIN_IDENTITY (nor the potential one for IOMMU_DOMAIN_BLOCKED), so giving PASIDs functional symmetry with devices would need significantly more work anyway. Thanks, Robin. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/5] iommu: Add blocking_domain_ops field in iommu_ops
Hi Jason, On 2022/5/16 21:57, Jason Gunthorpe wrote: On Mon, May 16, 2022 at 12:22:08PM +0100, Robin Murphy wrote: On 2022-05-16 02:57, Lu Baolu wrote: Each IOMMU driver must provide a blocking domain ops. If the hardware supports detaching domain from device, setting blocking domain equals detaching the existing domain from the deivce. Otherwise, an UNMANAGED domain without any mapping will be used instead. Unfortunately that's backwards - most of the implementations of .detach_dev are disabling translation entirely, meaning the device ends up effectively in passthrough rather than blocked. Ideally we'd convert the detach_dev of every driver into either a blocking or identity domain. The trick is knowing which is which.. I am still a bit puzzled about how the blocking_domain should be used when it is extended to support ->set_dev_pasid. If it's a blocking domain, the IOMMU driver knows that setting the blocking domain to device pasid means detaching the existing one. But if it's an identity domain, how could the IOMMU driver choose between: - setting the input domain to the pasid on device; or, - detaching the existing domain. I've ever thought about below solutions: - Checking the domain types and dispatching them to different operations. - Using different blocking domains for different types of domains. But both look rough. Guessing going down the list: apple dart - blocking, detach_dev calls apple_dart_hw_disable_dma() same as IOMMU_DOMAIN_BLOCKED [I wonder if this drive ris wrong in other ways though because I dont see a remove_streams in attach_dev] exynos - this seems to disable the 'sysmmu' so I'm guessing this is identity iommu-vmsa - Comment says 'disable mmu translaction' so I'm guessing this is idenity mkt_v1 - Code looks similar to mkt, which is probably identity. rkt - No idea sprd - No idea sun50i - This driver confusingly treats identity the same as unmanaged, seems wrong, no idea. amd - Not sure, clear_dte_entry() seems to set translation on but points the PTE to 0 ? Based on the spec table 8 I would have expected TV to be clear which would be blocking. Maybe a bug?? arm smmu qcomm - not sure intel - blocking These doesn't support default domains, so detach_dev should return back to DMA API ownership, which is either identity or something weird: fsl_pamu - identity due to the PPC use of dma direct msm mkt omap s390 - platform DMA ops terga-gart - Usually something called a GART would be 0 length once disabled, guessing blocking? tegra-smmu So, the approach here should be to go driver by driver and convert detach_dev to either identity, blocking or just delete it entirely, excluding the above 7 that don't support default domains. And get acks from the driver owners. Agreed. There seems to be a long way to go. I am wondering if we could decouple this refactoring from my new SVA API work? We can easily switch .detach_dev_pasid to using blocking domain later. Best regards, baolu ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/5] iommu: Add blocking_domain_ops field in iommu_ops
On Mon, May 16, 2022 at 12:22:08PM +0100, Robin Murphy wrote: > On 2022-05-16 02:57, Lu Baolu wrote: > > Each IOMMU driver must provide a blocking domain ops. If the hardware > > supports detaching domain from device, setting blocking domain equals > > detaching the existing domain from the deivce. Otherwise, an UNMANAGED > > domain without any mapping will be used instead. > > Unfortunately that's backwards - most of the implementations of .detach_dev > are disabling translation entirely, meaning the device ends up effectively > in passthrough rather than blocked. Ideally we'd convert the detach_dev of every driver into either a blocking or identity domain. The trick is knowing which is which.. Guessing going down the list: apple dart - blocking, detach_dev calls apple_dart_hw_disable_dma() same as IOMMU_DOMAIN_BLOCKED [I wonder if this drive ris wrong in other ways though because I dont see a remove_streams in attach_dev] exynos - this seems to disable the 'sysmmu' so I'm guessing this is identity iommu-vmsa - Comment says 'disable mmu translaction' so I'm guessing this is idenity mkt_v1 - Code looks similar to mkt, which is probably identity. rkt - No idea sprd - No idea sun50i - This driver confusingly treats identity the same as unmanaged, seems wrong, no idea. amd - Not sure, clear_dte_entry() seems to set translation on but points the PTE to 0 ? Based on the spec table 8 I would have expected TV to be clear which would be blocking. Maybe a bug?? arm smmu qcomm - not sure intel - blocking These doesn't support default domains, so detach_dev should return back to DMA API ownership, which is either identity or something weird: fsl_pamu - identity due to the PPC use of dma direct msm mkt omap s390 - platform DMA ops terga-gart - Usually something called a GART would be 0 length once disabled, guessing blocking? tegra-smmu So, the approach here should be to go driver by driver and convert detach_dev to either identity, blocking or just delete it entirely, excluding the above 7 that don't support default domains. And get acks from the driver owners. > Conversely, at least arm-smmu and arm-smmu-v3 could implement > IOMMU_DOMAIN_BLOCKED properly with fault-type S2CRs and STEs > respectively, it just needs a bit of wiring up. Given that vfio now uses them it seems worthwhile to do.. Jason ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/5] iommu: Add blocking_domain_ops field in iommu_ops
Hi Robin, On 2022/5/16 19:22, Robin Murphy wrote: On 2022-05-16 02:57, Lu Baolu wrote: Each IOMMU driver must provide a blocking domain ops. If the hardware supports detaching domain from device, setting blocking domain equals detaching the existing domain from the deivce. Otherwise, an UNMANAGED domain without any mapping will be used instead. Unfortunately that's backwards - most of the implementations of .detach_dev are disabling translation entirely, meaning the device ends up effectively in passthrough rather than blocked. Conversely, at least arm-smmu and arm-smmu-v3 could implement IOMMU_DOMAIN_BLOCKED properly with fault-type S2CRs and STEs respectively, it just needs a bit of wiring up. Thank you for letting me know this. This means that we need to add an additional UNMANAGED domain for each iommu group, although it is not used most of the time. If most IOMMU drivers could implement real dumb blocking domains, this burden may be reduced. Best regards, baolu ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/5] iommu: Add blocking_domain_ops field in iommu_ops
On Mon, May 16, 2022 at 12:27:41AM -0700, Christoph Hellwig wrote: > On Mon, May 16, 2022 at 09:57:56AM +0800, Lu Baolu wrote: > > Each IOMMU driver must provide a blocking domain ops. If the hardware > > supports detaching domain from device, setting blocking domain equals > > detaching the existing domain from the deivce. Otherwise, an UNMANAGED > > domain without any mapping will be used instead. > > blocking in this case means not allowing any access? The naming > sounds a bit odd to me as blocking in the kernel has a specific > meaning. Maybe something like noaccess ops might be a better name? It is because of this: include/linux/iommu.h: *IOMMU_DOMAIN_BLOCKED- All DMA is blocked, can be used to isolate include/linux/iommu.h:#define IOMMU_DOMAIN_BLOCKED (0U) noaccess might be clearer Jason ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/5] iommu: Add blocking_domain_ops field in iommu_ops
On 2022-05-16 02:57, Lu Baolu wrote: Each IOMMU driver must provide a blocking domain ops. If the hardware supports detaching domain from device, setting blocking domain equals detaching the existing domain from the deivce. Otherwise, an UNMANAGED domain without any mapping will be used instead. Unfortunately that's backwards - most of the implementations of .detach_dev are disabling translation entirely, meaning the device ends up effectively in passthrough rather than blocked. Conversely, at least arm-smmu and arm-smmu-v3 could implement IOMMU_DOMAIN_BLOCKED properly with fault-type S2CRs and STEs respectively, it just needs a bit of wiring up. Thanks, Robin. Signed-off-by: Lu Baolu --- include/linux/iommu.h | 7 +++ drivers/iommu/amd/iommu.c | 12 drivers/iommu/apple-dart.c | 12 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 3 +++ drivers/iommu/arm/arm-smmu/arm-smmu.c | 3 +++ drivers/iommu/arm/arm-smmu/qcom_iommu.c | 12 drivers/iommu/exynos-iommu.c| 12 drivers/iommu/fsl_pamu_domain.c | 12 drivers/iommu/intel/iommu.c | 12 drivers/iommu/ipmmu-vmsa.c | 12 drivers/iommu/msm_iommu.c | 12 drivers/iommu/mtk_iommu.c | 12 drivers/iommu/mtk_iommu_v1.c| 12 drivers/iommu/omap-iommu.c | 12 drivers/iommu/rockchip-iommu.c | 12 drivers/iommu/s390-iommu.c | 12 drivers/iommu/sprd-iommu.c | 11 +++ drivers/iommu/sun50i-iommu.c| 12 drivers/iommu/tegra-gart.c | 12 drivers/iommu/tegra-smmu.c | 12 drivers/iommu/virtio-iommu.c| 3 +++ 21 files changed, 219 insertions(+) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 572399ac1d83..5e228aad0ef6 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -216,6 +216,7 @@ struct iommu_iotlb_gather { *- IOMMU_DOMAIN_DMA: must use a dma domain *- 0: use the default setting * @default_domain_ops: the default ops for domains + * @blocking_domain_ops: the blocking ops for domains * @pgsize_bitmap: bitmap of all possible supported page sizes * @owner: Driver module providing these ops */ @@ -255,6 +256,7 @@ struct iommu_ops { int (*def_domain_type)(struct device *dev); const struct iommu_domain_ops *default_domain_ops; + const struct iommu_domain_ops *blocking_domain_ops; unsigned long pgsize_bitmap; struct module *owner; }; @@ -279,6 +281,9 @@ struct iommu_ops { * @enable_nesting: Enable nesting * @set_pgtable_quirks: Set io page table quirks (IO_PGTABLE_QUIRK_*) * @free: Release the domain after use. + * @blocking_domain_detach: iommu hardware support detaching a domain from + * a device, hence setting blocking domain to a device equals to + * detach the existing domain from it. */ struct iommu_domain_ops { int (*set_dev)(struct iommu_domain *domain, struct device *dev); @@ -310,6 +315,8 @@ struct iommu_domain_ops { unsigned long quirks); void (*free)(struct iommu_domain *domain); + + unsigned int blocking_domain_detach:1; }; /** diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index 01b8668ef46d..c66713439824 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -2272,6 +2272,14 @@ static bool amd_iommu_enforce_cache_coherency(struct iommu_domain *domain) return true; } +static int amd_blocking_domain_set_dev(struct iommu_domain *domain, + struct device *dev) +{ + amd_iommu_detach_device(domain, dev); + + return 0; +} + const struct iommu_ops amd_iommu_ops = { .capable = amd_iommu_capable, .domain_alloc = amd_iommu_domain_alloc, @@ -2295,6 +2303,10 @@ const struct iommu_ops amd_iommu_ops = { .iotlb_sync = amd_iommu_iotlb_sync, .free = amd_iommu_domain_free, .enforce_cache_coherency = amd_iommu_enforce_cache_coherency, + }, + .blocking_domain_ops = &(const struct iommu_domain_ops) { + .set_dev= amd_blocking_domain_set_dev, + .blocking_domain_detach = true, } }; diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c index a0b7281f1989..3c37762e01ec 100644 --- a/drivers/iommu/apple-dart.c +++ b/drivers/iommu/apple-dart.c @@ -763,6 +763,14 @@ static void apple_dart_get_resv_regions(struct device *dev, iommu_dma_get_resv_regions(dev, head); }
Re: [PATCH 2/5] iommu: Add blocking_domain_ops field in iommu_ops
On Mon, May 16, 2022 at 09:57:56AM +0800, Lu Baolu wrote: > Each IOMMU driver must provide a blocking domain ops. If the hardware > supports detaching domain from device, setting blocking domain equals > detaching the existing domain from the deivce. Otherwise, an UNMANAGED > domain without any mapping will be used instead. blocking in this case means not allowing any access? The naming sounds a bit odd to me as blocking in the kernel has a specific meaning. Maybe something like noaccess ops might be a better name? ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 2/5] iommu: Add blocking_domain_ops field in iommu_ops
Each IOMMU driver must provide a blocking domain ops. If the hardware supports detaching domain from device, setting blocking domain equals detaching the existing domain from the deivce. Otherwise, an UNMANAGED domain without any mapping will be used instead. Signed-off-by: Lu Baolu --- include/linux/iommu.h | 7 +++ drivers/iommu/amd/iommu.c | 12 drivers/iommu/apple-dart.c | 12 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 3 +++ drivers/iommu/arm/arm-smmu/arm-smmu.c | 3 +++ drivers/iommu/arm/arm-smmu/qcom_iommu.c | 12 drivers/iommu/exynos-iommu.c| 12 drivers/iommu/fsl_pamu_domain.c | 12 drivers/iommu/intel/iommu.c | 12 drivers/iommu/ipmmu-vmsa.c | 12 drivers/iommu/msm_iommu.c | 12 drivers/iommu/mtk_iommu.c | 12 drivers/iommu/mtk_iommu_v1.c| 12 drivers/iommu/omap-iommu.c | 12 drivers/iommu/rockchip-iommu.c | 12 drivers/iommu/s390-iommu.c | 12 drivers/iommu/sprd-iommu.c | 11 +++ drivers/iommu/sun50i-iommu.c| 12 drivers/iommu/tegra-gart.c | 12 drivers/iommu/tegra-smmu.c | 12 drivers/iommu/virtio-iommu.c| 3 +++ 21 files changed, 219 insertions(+) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 572399ac1d83..5e228aad0ef6 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -216,6 +216,7 @@ struct iommu_iotlb_gather { * - IOMMU_DOMAIN_DMA: must use a dma domain * - 0: use the default setting * @default_domain_ops: the default ops for domains + * @blocking_domain_ops: the blocking ops for domains * @pgsize_bitmap: bitmap of all possible supported page sizes * @owner: Driver module providing these ops */ @@ -255,6 +256,7 @@ struct iommu_ops { int (*def_domain_type)(struct device *dev); const struct iommu_domain_ops *default_domain_ops; + const struct iommu_domain_ops *blocking_domain_ops; unsigned long pgsize_bitmap; struct module *owner; }; @@ -279,6 +281,9 @@ struct iommu_ops { * @enable_nesting: Enable nesting * @set_pgtable_quirks: Set io page table quirks (IO_PGTABLE_QUIRK_*) * @free: Release the domain after use. + * @blocking_domain_detach: iommu hardware support detaching a domain from + * a device, hence setting blocking domain to a device equals to + * detach the existing domain from it. */ struct iommu_domain_ops { int (*set_dev)(struct iommu_domain *domain, struct device *dev); @@ -310,6 +315,8 @@ struct iommu_domain_ops { unsigned long quirks); void (*free)(struct iommu_domain *domain); + + unsigned int blocking_domain_detach:1; }; /** diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index 01b8668ef46d..c66713439824 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -2272,6 +2272,14 @@ static bool amd_iommu_enforce_cache_coherency(struct iommu_domain *domain) return true; } +static int amd_blocking_domain_set_dev(struct iommu_domain *domain, + struct device *dev) +{ + amd_iommu_detach_device(domain, dev); + + return 0; +} + const struct iommu_ops amd_iommu_ops = { .capable = amd_iommu_capable, .domain_alloc = amd_iommu_domain_alloc, @@ -2295,6 +2303,10 @@ const struct iommu_ops amd_iommu_ops = { .iotlb_sync = amd_iommu_iotlb_sync, .free = amd_iommu_domain_free, .enforce_cache_coherency = amd_iommu_enforce_cache_coherency, + }, + .blocking_domain_ops = &(const struct iommu_domain_ops) { + .set_dev= amd_blocking_domain_set_dev, + .blocking_domain_detach = true, } }; diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c index a0b7281f1989..3c37762e01ec 100644 --- a/drivers/iommu/apple-dart.c +++ b/drivers/iommu/apple-dart.c @@ -763,6 +763,14 @@ static void apple_dart_get_resv_regions(struct device *dev, iommu_dma_get_resv_regions(dev, head); } +static int apple_dart_blocking_domain_set_dev(struct iommu_domain *domain, + struct device *dev) +{ + apple_dart_detach_dev(domain, dev); + + return 0; +} + static const struct iommu_ops apple_dart_iommu_ops = { .domain_alloc = apple_dart_domain_alloc, .probe_device = apple_dart_probe_device, @@ -784,6 +792,10 @@ static const struct iommu_ops apple_dart_iommu_ops = {