2022-05-16 07:34:55

by Lu Baolu

[permalink] [raw]
Subject: [PATCH 0/5] iommu: Make blocking domain static for group

Hi folks,

This is a follow-up series after several discussions on blocking domain.
The latest discussion could be found here.

https://lore.kernel.org/linux-iommu/[email protected]/

This makes blocking domain static by:

- Each IOMMU driver is required to report domain ops for the blocking
domain in its iommu_ops. Some IOMMU drivers support detaching domain
by clearing an entry in the device context, while others not. To
distinguish this capability among the IOMMU drivers, a flag is added
to the domain ops.

- Similar to the default domain, each iommu group also has a static
blokcing domain. The blocking domain is allocated when the first
device joins the group and freed after the last device leaves.

- As .detach_dev equals to either setting the default domain or blocking
domain to the device, this callback is not needed anymore. It is
removed in this series.

Please kindly review and suggest. Very appreciated.

Best regards,
baolu

Lu Baolu (5):
iommu: Rename attach_dev to set_dev in domain ops
iommu: Add blocking_domain_ops field in iommu_ops
iommu: Make blocking domain static for iommu group
iommu: Use blocking domain for empty domain attaching
iommu: Remove .detach_dev from iommu domain ops

include/linux/iommu.h | 13 ++-
include/trace/events/iommu.h | 7 --
drivers/iommu/amd/iommu.c | 15 ++-
drivers/iommu/apple-dart.c | 15 ++-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 5 +-
drivers/iommu/arm/arm-smmu/arm-smmu.c | 5 +-
drivers/iommu/arm/arm-smmu/qcom_iommu.c | 15 ++-
drivers/iommu/exynos-iommu.c | 15 ++-
drivers/iommu/fsl_pamu_domain.c | 15 ++-
drivers/iommu/intel/iommu.c | 15 ++-
drivers/iommu/iommu-traces.c | 1 -
drivers/iommu/iommu.c | 122 ++++++++++----------
drivers/iommu/ipmmu-vmsa.c | 15 ++-
drivers/iommu/msm_iommu.c | 15 ++-
drivers/iommu/mtk_iommu.c | 15 ++-
drivers/iommu/mtk_iommu_v1.c | 15 ++-
drivers/iommu/omap-iommu.c | 15 ++-
drivers/iommu/rockchip-iommu.c | 15 ++-
drivers/iommu/s390-iommu.c | 15 ++-
drivers/iommu/sprd-iommu.c | 14 ++-
drivers/iommu/sun50i-iommu.c | 15 ++-
drivers/iommu/tegra-gart.c | 15 ++-
drivers/iommu/tegra-smmu.c | 15 ++-
drivers/iommu/virtio-iommu.c | 5 +-
24 files changed, 299 insertions(+), 113 deletions(-)

--
2.25.1



2022-05-16 08:28:19

by Lu Baolu

[permalink] [raw]
Subject: [PATCH 5/5] iommu: Remove .detach_dev from iommu domain ops

The .detach_dev callback is not used anymore. Reomve it to avoid dead
code.

Signed-off-by: Lu Baolu <[email protected]>
---
include/linux/iommu.h | 2 --
include/trace/events/iommu.h | 7 -------
drivers/iommu/amd/iommu.c | 1 -
drivers/iommu/apple-dart.c | 1 -
drivers/iommu/arm/arm-smmu/qcom_iommu.c | 1 -
drivers/iommu/exynos-iommu.c | 1 -
drivers/iommu/fsl_pamu_domain.c | 1 -
drivers/iommu/intel/iommu.c | 1 -
drivers/iommu/iommu-traces.c | 1 -
drivers/iommu/ipmmu-vmsa.c | 1 -
drivers/iommu/msm_iommu.c | 1 -
drivers/iommu/mtk_iommu.c | 1 -
drivers/iommu/mtk_iommu_v1.c | 1 -
drivers/iommu/omap-iommu.c | 1 -
drivers/iommu/rockchip-iommu.c | 1 -
drivers/iommu/s390-iommu.c | 1 -
drivers/iommu/sprd-iommu.c | 1 -
drivers/iommu/sun50i-iommu.c | 1 -
drivers/iommu/tegra-gart.c | 1 -
drivers/iommu/tegra-smmu.c | 1 -
20 files changed, 27 deletions(-)

diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 5e228aad0ef6..a8c87ebef02d 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -264,7 +264,6 @@ struct iommu_ops {
/**
* struct iommu_domain_ops - domain specific operations
* @set_dev: set an iommu domain to a device
- * @detach_dev: detach an iommu domain from a device
* @map: map a physically contiguous memory region to an iommu domain
* @map_pages: map a physically contiguous set of pages of the same size to
* an iommu domain.
@@ -287,7 +286,6 @@ struct iommu_ops {
*/
struct iommu_domain_ops {
int (*set_dev)(struct iommu_domain *domain, struct device *dev);
- void (*detach_dev)(struct iommu_domain *domain, struct device *dev);

int (*map)(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot, gfp_t gfp);
diff --git a/include/trace/events/iommu.h b/include/trace/events/iommu.h
index 29096fe12623..70743db1fb75 100644
--- a/include/trace/events/iommu.h
+++ b/include/trace/events/iommu.h
@@ -76,13 +76,6 @@ DEFINE_EVENT(iommu_device_event, attach_device_to_domain,
TP_ARGS(dev)
);

-DEFINE_EVENT(iommu_device_event, detach_device_from_domain,
-
- TP_PROTO(struct device *dev),
-
- TP_ARGS(dev)
-);
-
TRACE_EVENT(map,

TP_PROTO(unsigned long iova, phys_addr_t paddr, size_t size),
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index c66713439824..9ccf289196be 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -2294,7 +2294,6 @@ const struct iommu_ops amd_iommu_ops = {
.def_domain_type = amd_iommu_def_domain_type,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = amd_iommu_attach_device,
- .detach_dev = amd_iommu_detach_device,
.map = amd_iommu_map,
.unmap = amd_iommu_unmap,
.iotlb_sync_map = amd_iommu_iotlb_sync_map,
diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index 3c37762e01ec..640f2ebeba0c 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -784,7 +784,6 @@ static const struct iommu_ops apple_dart_iommu_ops = {
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = apple_dart_attach_dev,
- .detach_dev = apple_dart_detach_dev,
.map_pages = apple_dart_map_pages,
.unmap_pages = apple_dart_unmap_pages,
.flush_iotlb_all = apple_dart_flush_iotlb_all,
diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
index dee9b5a3a324..b6400458bcdb 100644
--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
@@ -605,7 +605,6 @@ static const struct iommu_ops qcom_iommu_ops = {
.pgsize_bitmap = SZ_4K | SZ_64K | SZ_1M | SZ_16M,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = qcom_iommu_attach_dev,
- .detach_dev = qcom_iommu_detach_dev,
.map = qcom_iommu_map,
.unmap = qcom_iommu_unmap,
.flush_iotlb_all = qcom_iommu_flush_iotlb_all,
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index bbecb9a2a554..0ed3ac3f6b28 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1324,7 +1324,6 @@ static const struct iommu_ops exynos_iommu_ops = {
.of_xlate = exynos_iommu_of_xlate,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = exynos_iommu_attach_device,
- .detach_dev = exynos_iommu_detach_device,
.map = exynos_iommu_map,
.unmap = exynos_iommu_unmap,
.iova_to_phys = exynos_iommu_iova_to_phys,
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index 92fc320f8c83..8e32d7942835 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -467,7 +467,6 @@ static const struct iommu_ops fsl_pamu_ops = {
.device_group = fsl_pamu_device_group,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = fsl_pamu_attach_device,
- .detach_dev = fsl_pamu_detach_device,
.iova_to_phys = fsl_pamu_iova_to_phys,
.free = fsl_pamu_domain_free,
},
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 2060e8a540b3..9b6b3d38de46 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -4934,7 +4934,6 @@ const struct iommu_ops intel_iommu_ops = {
#endif
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = intel_iommu_attach_device,
- .detach_dev = intel_iommu_detach_device,
.map_pages = intel_iommu_map_pages,
.unmap_pages = intel_iommu_unmap_pages,
.iotlb_sync_map = intel_iommu_iotlb_sync_map,
diff --git a/drivers/iommu/iommu-traces.c b/drivers/iommu/iommu-traces.c
index 1e9ca7789de1..23416bf76df9 100644
--- a/drivers/iommu/iommu-traces.c
+++ b/drivers/iommu/iommu-traces.c
@@ -18,7 +18,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(remove_device_from_group);

/* iommu_device_event */
EXPORT_TRACEPOINT_SYMBOL_GPL(attach_device_to_domain);
-EXPORT_TRACEPOINT_SYMBOL_GPL(detach_device_from_domain);

/* iommu_map_unmap */
EXPORT_TRACEPOINT_SYMBOL_GPL(map);
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 72982d1277c2..5803f6175a46 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -886,7 +886,6 @@ static const struct iommu_ops ipmmu_ops = {
.of_xlate = ipmmu_of_xlate,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = ipmmu_attach_device,
- .detach_dev = ipmmu_detach_device,
.map = ipmmu_map,
.unmap = ipmmu_unmap,
.flush_iotlb_all = ipmmu_flush_iotlb_all,
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index b0471d03db60..3f3ce24e1db6 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -691,7 +691,6 @@ static struct iommu_ops msm_iommu_ops = {
.of_xlate = qcom_iommu_of_xlate,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = msm_iommu_attach_dev,
- .detach_dev = msm_iommu_detach_dev,
.map = msm_iommu_map,
.unmap = msm_iommu_unmap,
/*
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index cc8d80290498..63cb4379314c 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -946,7 +946,6 @@ static const struct iommu_ops mtk_iommu_ops = {
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = mtk_iommu_attach_device,
- .detach_dev = mtk_iommu_detach_device,
.map = mtk_iommu_map,
.unmap = mtk_iommu_unmap,
.flush_iotlb_all = mtk_iommu_flush_iotlb_all,
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 894d2526ba4c..3ffaadcf9a30 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -603,7 +603,6 @@ static const struct iommu_ops mtk_iommu_v1_ops = {
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = mtk_iommu_v1_attach_device,
- .detach_dev = mtk_iommu_v1_detach_device,
.map = mtk_iommu_v1_map,
.unmap = mtk_iommu_v1_unmap,
.iova_to_phys = mtk_iommu_v1_iova_to_phys,
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 7e6ba6f1218d..33ba73be932a 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1748,7 +1748,6 @@ static const struct iommu_ops omap_iommu_ops = {
.pgsize_bitmap = OMAP_IOMMU_PGSIZES,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = omap_iommu_attach_dev,
- .detach_dev = omap_iommu_detach_dev,
.map = omap_iommu_map,
.unmap = omap_iommu_unmap,
.iova_to_phys = omap_iommu_iova_to_phys,
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 29c803759a0b..3d3baad1bc36 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1202,7 +1202,6 @@ static const struct iommu_ops rk_iommu_ops = {
.of_xlate = rk_iommu_of_xlate,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = rk_iommu_attach_device,
- .detach_dev = rk_iommu_detach_device,
.map = rk_iommu_map,
.unmap = rk_iommu_unmap,
.iova_to_phys = rk_iommu_iova_to_phys,
diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c
index a03bff562a44..e9ad001d086b 100644
--- a/drivers/iommu/s390-iommu.c
+++ b/drivers/iommu/s390-iommu.c
@@ -377,7 +377,6 @@ static const struct iommu_ops s390_iommu_ops = {
.pgsize_bitmap = S390_IOMMU_PGSIZES,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = s390_iommu_attach_device,
- .detach_dev = s390_iommu_detach_device,
.map = s390_iommu_map,
.unmap = s390_iommu_unmap,
.iova_to_phys = s390_iommu_iova_to_phys,
diff --git a/drivers/iommu/sprd-iommu.c b/drivers/iommu/sprd-iommu.c
index ab62063cee5b..b732cd894725 100644
--- a/drivers/iommu/sprd-iommu.c
+++ b/drivers/iommu/sprd-iommu.c
@@ -431,7 +431,6 @@ static const struct iommu_ops sprd_iommu_ops = {
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = sprd_iommu_attach_device,
- .detach_dev = sprd_iommu_detach_device,
.map = sprd_iommu_map,
.unmap = sprd_iommu_unmap,
.iotlb_sync_map = sprd_iommu_sync_map,
diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
index a51a55ae0634..12da8e4fdef9 100644
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -775,7 +775,6 @@ static const struct iommu_ops sun50i_iommu_ops = {
.release_device = sun50i_iommu_release_device,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = sun50i_iommu_attach_device,
- .detach_dev = sun50i_iommu_detach_device,
.flush_iotlb_all = sun50i_iommu_flush_iotlb_all,
.iotlb_sync = sun50i_iommu_iotlb_sync,
.iova_to_phys = sun50i_iommu_iova_to_phys,
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c
index 7e2aef7ae72e..152a04dd5753 100644
--- a/drivers/iommu/tegra-gart.c
+++ b/drivers/iommu/tegra-gart.c
@@ -287,7 +287,6 @@ static const struct iommu_ops gart_iommu_ops = {
.of_xlate = gart_iommu_of_xlate,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = gart_iommu_attach_dev,
- .detach_dev = gart_iommu_detach_dev,
.map = gart_iommu_map,
.unmap = gart_iommu_unmap,
.iova_to_phys = gart_iommu_iova_to_phys,
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index fe2c463db230..f35ee4d07a33 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -980,7 +980,6 @@ static const struct iommu_ops tegra_smmu_ops = {
.pgsize_bitmap = SZ_4K,
.default_domain_ops = &(const struct iommu_domain_ops) {
.set_dev = tegra_smmu_attach_dev,
- .detach_dev = tegra_smmu_detach_dev,
.map = tegra_smmu_map,
.unmap = tegra_smmu_unmap,
.iova_to_phys = tegra_smmu_iova_to_phys,
--
2.25.1


2022-05-16 14:56:50

by Lu Baolu

[permalink] [raw]
Subject: [PATCH 1/5] iommu: Rename attach_dev to set_dev in domain ops

The detach callback of the iommu domain ops is not used in some IOMMU
drivers. The detach_dev actually means setting a default domain or a
blocking domain to the device. As attach_dev actually acts as setting
domain for a device, this renames attach_dev to set_dev to reflect the
actual usage.

Suggested-by: Jason Gunthorpe <[email protected]>
Signed-off-by: Lu Baolu <[email protected]>
---
include/linux/iommu.h | 4 ++--
drivers/iommu/amd/iommu.c | 2 +-
drivers/iommu/apple-dart.c | 2 +-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +-
drivers/iommu/arm/arm-smmu/arm-smmu.c | 2 +-
drivers/iommu/arm/arm-smmu/qcom_iommu.c | 2 +-
drivers/iommu/exynos-iommu.c | 2 +-
drivers/iommu/fsl_pamu_domain.c | 2 +-
drivers/iommu/intel/iommu.c | 2 +-
drivers/iommu/iommu.c | 6 +++---
drivers/iommu/ipmmu-vmsa.c | 2 +-
drivers/iommu/msm_iommu.c | 2 +-
drivers/iommu/mtk_iommu.c | 2 +-
drivers/iommu/mtk_iommu_v1.c | 2 +-
drivers/iommu/omap-iommu.c | 2 +-
drivers/iommu/rockchip-iommu.c | 2 +-
drivers/iommu/s390-iommu.c | 2 +-
drivers/iommu/sprd-iommu.c | 2 +-
drivers/iommu/sun50i-iommu.c | 2 +-
drivers/iommu/tegra-gart.c | 2 +-
drivers/iommu/tegra-smmu.c | 2 +-
drivers/iommu/virtio-iommu.c | 2 +-
22 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 5e1afe169549..572399ac1d83 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -261,7 +261,7 @@ struct iommu_ops {

/**
* struct iommu_domain_ops - domain specific operations
- * @attach_dev: attach an iommu domain to a device
+ * @set_dev: set an iommu domain to a device
* @detach_dev: detach an iommu domain from a device
* @map: map a physically contiguous memory region to an iommu domain
* @map_pages: map a physically contiguous set of pages of the same size to
@@ -281,7 +281,7 @@ struct iommu_ops {
* @free: Release the domain after use.
*/
struct iommu_domain_ops {
- int (*attach_dev)(struct iommu_domain *domain, struct device *dev);
+ int (*set_dev)(struct iommu_domain *domain, struct device *dev);
void (*detach_dev)(struct iommu_domain *domain, struct device *dev);

int (*map)(struct iommu_domain *domain, unsigned long iova,
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 840831d5d2ad..01b8668ef46d 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -2285,7 +2285,7 @@ const struct iommu_ops amd_iommu_ops = {
.pgsize_bitmap = AMD_IOMMU_PGSIZES,
.def_domain_type = amd_iommu_def_domain_type,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = amd_iommu_attach_device,
+ .set_dev = amd_iommu_attach_device,
.detach_dev = amd_iommu_detach_device,
.map = amd_iommu_map,
.unmap = amd_iommu_unmap,
diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index 8af0242a90d9..a0b7281f1989 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -775,7 +775,7 @@ static const struct iommu_ops apple_dart_iommu_ops = {
.pgsize_bitmap = -1UL, /* Restricted during dart probe */
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = apple_dart_attach_dev,
+ .set_dev = apple_dart_attach_dev,
.detach_dev = apple_dart_detach_dev,
.map_pages = apple_dart_map_pages,
.unmap_pages = apple_dart_unmap_pages,
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 88817a3376ef..7e7d9e0b7aee 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2859,7 +2859,7 @@ static struct iommu_ops arm_smmu_ops = {
.pgsize_bitmap = -1UL, /* Restricted during device attach */
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = arm_smmu_attach_dev,
+ .set_dev = arm_smmu_attach_dev,
.map_pages = arm_smmu_map_pages,
.unmap_pages = arm_smmu_unmap_pages,
.flush_iotlb_all = arm_smmu_flush_iotlb_all,
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 2ed3594f384e..c91d12b7e283 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -1597,7 +1597,7 @@ static struct iommu_ops arm_smmu_ops = {
.pgsize_bitmap = -1UL, /* Restricted during device attach */
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = arm_smmu_attach_dev,
+ .set_dev = arm_smmu_attach_dev,
.map_pages = arm_smmu_map_pages,
.unmap_pages = arm_smmu_unmap_pages,
.flush_iotlb_all = arm_smmu_flush_iotlb_all,
diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
index 4c077c38fbd6..cf624bd305e0 100644
--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
@@ -596,7 +596,7 @@ static const struct iommu_ops qcom_iommu_ops = {
.of_xlate = qcom_iommu_of_xlate,
.pgsize_bitmap = SZ_4K | SZ_64K | SZ_1M | SZ_16M,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = qcom_iommu_attach_dev,
+ .set_dev = qcom_iommu_attach_dev,
.detach_dev = qcom_iommu_detach_dev,
.map = qcom_iommu_map,
.unmap = qcom_iommu_unmap,
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 71f2018e23fe..797348f3440e 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1315,7 +1315,7 @@ static const struct iommu_ops exynos_iommu_ops = {
.pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE,
.of_xlate = exynos_iommu_of_xlate,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = exynos_iommu_attach_device,
+ .set_dev = exynos_iommu_attach_device,
.detach_dev = exynos_iommu_detach_device,
.map = exynos_iommu_map,
.unmap = exynos_iommu_unmap,
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index 94b4589dc67c..7512c8e007e9 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -458,7 +458,7 @@ static const struct iommu_ops fsl_pamu_ops = {
.release_device = fsl_pamu_release_device,
.device_group = fsl_pamu_device_group,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = fsl_pamu_attach_device,
+ .set_dev = fsl_pamu_attach_device,
.detach_dev = fsl_pamu_detach_device,
.iova_to_phys = fsl_pamu_iova_to_phys,
.free = fsl_pamu_domain_free,
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index e56b3a4b6998..6abc1fbbd461 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -4925,7 +4925,7 @@ const struct iommu_ops intel_iommu_ops = {
.page_response = intel_svm_page_response,
#endif
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = intel_iommu_attach_device,
+ .set_dev = intel_iommu_attach_device,
.detach_dev = intel_iommu_detach_device,
.map_pages = intel_iommu_map_pages,
.unmap_pages = intel_iommu_unmap_pages,
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 847ad47a2dfd..8eba26be4363 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1963,10 +1963,10 @@ static int __iommu_attach_device(struct iommu_domain *domain,
{
int ret;

- if (unlikely(domain->ops->attach_dev == NULL))
+ if (unlikely(domain->ops->set_dev == NULL))
return -ENODEV;

- ret = domain->ops->attach_dev(domain, dev);
+ ret = domain->ops->set_dev(domain, dev);
if (!ret)
trace_attach_device_to_domain(dev);
return ret;
@@ -2142,7 +2142,7 @@ static int __iommu_group_set_domain(struct iommu_group *group,
}

/*
- * Changing the domain is done by calling attach_dev() on the new
+ * Changing the domain is done by calling set_dev() on the new
* domain. This switch does not have to be atomic and DMA can be
* discarded during the transition. DMA must only be able to access
* either new_domain or group->domain, never something else.
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 8fdb84b3642b..b361a4cff688 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -877,7 +877,7 @@ static const struct iommu_ops ipmmu_ops = {
.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
.of_xlate = ipmmu_of_xlate,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = ipmmu_attach_device,
+ .set_dev = ipmmu_attach_device,
.detach_dev = ipmmu_detach_device,
.map = ipmmu_map,
.unmap = ipmmu_unmap,
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index f09aedfdd462..569d36840b67 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -682,7 +682,7 @@ static struct iommu_ops msm_iommu_ops = {
.pgsize_bitmap = MSM_IOMMU_PGSIZES,
.of_xlate = qcom_iommu_of_xlate,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = msm_iommu_attach_dev,
+ .set_dev = msm_iommu_attach_dev,
.detach_dev = msm_iommu_detach_dev,
.map = msm_iommu_map,
.unmap = msm_iommu_unmap,
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index bb9dd92c9898..33ec401d40eb 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -937,7 +937,7 @@ static const struct iommu_ops mtk_iommu_ops = {
.pgsize_bitmap = SZ_4K | SZ_64K | SZ_1M | SZ_16M,
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = mtk_iommu_attach_device,
+ .set_dev = mtk_iommu_attach_device,
.detach_dev = mtk_iommu_detach_device,
.map = mtk_iommu_map,
.unmap = mtk_iommu_unmap,
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index e1cb51b9866c..fb55802fb841 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -594,7 +594,7 @@ static const struct iommu_ops mtk_iommu_v1_ops = {
.pgsize_bitmap = ~0UL << MT2701_IOMMU_PAGE_SHIFT,
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = mtk_iommu_v1_attach_device,
+ .set_dev = mtk_iommu_v1_attach_device,
.detach_dev = mtk_iommu_v1_detach_device,
.map = mtk_iommu_v1_map,
.unmap = mtk_iommu_v1_unmap,
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index d9cf2820c02e..6720dcb437a0 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1739,7 +1739,7 @@ static const struct iommu_ops omap_iommu_ops = {
.device_group = omap_iommu_device_group,
.pgsize_bitmap = OMAP_IOMMU_PGSIZES,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = omap_iommu_attach_dev,
+ .set_dev = omap_iommu_attach_dev,
.detach_dev = omap_iommu_detach_dev,
.map = omap_iommu_map,
.unmap = omap_iommu_unmap,
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index ab57c4b8fade..0a4196c34179 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1193,7 +1193,7 @@ static const struct iommu_ops rk_iommu_ops = {
.pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP,
.of_xlate = rk_iommu_of_xlate,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = rk_iommu_attach_device,
+ .set_dev = rk_iommu_attach_device,
.detach_dev = rk_iommu_detach_device,
.map = rk_iommu_map,
.unmap = rk_iommu_unmap,
diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c
index 3833e86c6e7b..cde01c72f573 100644
--- a/drivers/iommu/s390-iommu.c
+++ b/drivers/iommu/s390-iommu.c
@@ -368,7 +368,7 @@ static const struct iommu_ops s390_iommu_ops = {
.device_group = generic_device_group,
.pgsize_bitmap = S390_IOMMU_PGSIZES,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = s390_iommu_attach_device,
+ .set_dev = s390_iommu_attach_device,
.detach_dev = s390_iommu_detach_device,
.map = s390_iommu_map,
.unmap = s390_iommu_unmap,
diff --git a/drivers/iommu/sprd-iommu.c b/drivers/iommu/sprd-iommu.c
index bd409bab6286..45b58845f5f8 100644
--- a/drivers/iommu/sprd-iommu.c
+++ b/drivers/iommu/sprd-iommu.c
@@ -423,7 +423,7 @@ static const struct iommu_ops sprd_iommu_ops = {
.pgsize_bitmap = ~0UL << SPRD_IOMMU_PAGE_SHIFT,
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = sprd_iommu_attach_device,
+ .set_dev = sprd_iommu_attach_device,
.detach_dev = sprd_iommu_detach_device,
.map = sprd_iommu_map,
.unmap = sprd_iommu_unmap,
diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
index c54ab477b8fd..041b30463552 100644
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -766,7 +766,7 @@ static const struct iommu_ops sun50i_iommu_ops = {
.probe_device = sun50i_iommu_probe_device,
.release_device = sun50i_iommu_release_device,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = sun50i_iommu_attach_device,
+ .set_dev = sun50i_iommu_attach_device,
.detach_dev = sun50i_iommu_detach_device,
.flush_iotlb_all = sun50i_iommu_flush_iotlb_all,
.iotlb_sync = sun50i_iommu_iotlb_sync,
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c
index a6700a40a6f8..f083a9fba4d0 100644
--- a/drivers/iommu/tegra-gart.c
+++ b/drivers/iommu/tegra-gart.c
@@ -278,7 +278,7 @@ static const struct iommu_ops gart_iommu_ops = {
.pgsize_bitmap = GART_IOMMU_PGSIZES,
.of_xlate = gart_iommu_of_xlate,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = gart_iommu_attach_dev,
+ .set_dev = gart_iommu_attach_dev,
.detach_dev = gart_iommu_detach_dev,
.map = gart_iommu_map,
.unmap = gart_iommu_unmap,
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 1fea68e551f1..36e9c2864e3f 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -971,7 +971,7 @@ static const struct iommu_ops tegra_smmu_ops = {
.of_xlate = tegra_smmu_of_xlate,
.pgsize_bitmap = SZ_4K,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = tegra_smmu_attach_dev,
+ .set_dev = tegra_smmu_attach_dev,
.detach_dev = tegra_smmu_detach_dev,
.map = tegra_smmu_map,
.unmap = tegra_smmu_unmap,
diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 25be4b822aa0..ce2bd01806d8 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -1017,7 +1017,7 @@ static struct iommu_ops viommu_ops = {
.of_xlate = viommu_of_xlate,
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
- .attach_dev = viommu_attach_dev,
+ .set_dev = viommu_attach_dev,
.map = viommu_map,
.unmap = viommu_unmap,
.iova_to_phys = viommu_iova_to_phys,
--
2.25.1


2022-05-16 14:59:25

by Lu Baolu

[permalink] [raw]
Subject: [PATCH 4/5] iommu: Use blocking domain for empty domain attaching

If a NULL domain is about to set to a device, let's set the blocking
domain instead.

Signed-off-by: Lu Baolu <[email protected]>
---
drivers/iommu/iommu.c | 35 +++--------------------------------
1 file changed, 3 insertions(+), 32 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index dcbc55c9d8d7..ba0f427c2823 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2058,16 +2058,6 @@ int iommu_deferred_attach(struct device *dev, struct iommu_domain *domain)
return 0;
}

-static void __iommu_detach_device(struct iommu_domain *domain,
- struct device *dev)
-{
- if (iommu_is_attach_deferred(dev))
- return;
-
- domain->ops->detach_dev(domain, dev);
- trace_detach_device_from_domain(dev);
-}
-
void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
{
struct iommu_group *group;
@@ -2160,15 +2150,6 @@ int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group)
}
EXPORT_SYMBOL_GPL(iommu_attach_group);

-static int iommu_group_do_detach_device(struct device *dev, void *data)
-{
- struct iommu_domain *domain = data;
-
- __iommu_detach_device(domain, dev);
-
- return 0;
-}
-
static int __iommu_group_set_domain(struct iommu_group *group,
struct iommu_domain *new_domain)
{
@@ -2177,19 +2158,9 @@ static int __iommu_group_set_domain(struct iommu_group *group,
if (group->domain == new_domain)
return 0;

- /*
- * New drivers should support default domains and so the detach_dev() op
- * will never be called. Otherwise the NULL domain represents some
- * platform specific behavior.
- */
- if (!new_domain) {
- if (WARN_ON(!group->domain->ops->detach_dev))
- return -EINVAL;
- __iommu_group_for_each_dev(group, group->domain,
- iommu_group_do_detach_device);
- group->domain = NULL;
- return 0;
- }
+ /* The NULL domain represents some platform specific behavior. */
+ if (!new_domain)
+ new_domain = group->blocking_domain;

/*
* Changing the domain is done by calling set_dev() on the new
--
2.25.1


2022-05-16 16:10:41

by Lu Baolu

[permalink] [raw]
Subject: [PATCH 3/5] iommu: Make blocking domain static for iommu group

This makes the blocking_domain static for an iommu group. It's allocated
when the first device joins the group and freed after the last device
leaves. Essentially the blocking domain is a dummy domain used to remove
the domain from IOMMU's device context. Unfortunately, some IOMMU devices
don't provide such capability. In this case, we use an UNMANAGED domain
without any mapping instead.

Signed-off-by: Lu Baolu <[email protected]>
---
drivers/iommu/iommu.c | 85 +++++++++++++++++++++++++++----------------
1 file changed, 54 insertions(+), 31 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 8eba26be4363..dcbc55c9d8d7 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -604,8 +604,6 @@ static void iommu_group_release(struct kobject *kobj)

if (group->default_domain)
iommu_domain_free(group->default_domain);
- if (group->blocking_domain)
- iommu_domain_free(group->blocking_domain);

kfree(group->name);
kfree(group);
@@ -854,6 +852,46 @@ static bool iommu_is_attach_deferred(struct device *dev)
return false;
}

+static int iommu_group_alloc_blocking_domain(struct iommu_group *group,
+ struct device *dev)
+{
+ struct iommu_domain *domain;
+ const struct iommu_ops *iommu_ops = dev_iommu_ops(dev);
+ const struct iommu_domain_ops *ops = iommu_ops->blocking_domain_ops;
+
+ if (group->blocking_domain)
+ return 0;
+
+ if (ops->blocking_domain_detach) {
+ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+ if (domain)
+ domain->type = IOMMU_DOMAIN_BLOCKED;
+ } else {
+ domain = __iommu_domain_alloc(dev->bus, IOMMU_DOMAIN_UNMANAGED);
+ }
+
+ if (!domain)
+ return -ENOMEM;
+
+ domain->ops = ops;
+ group->blocking_domain = domain;
+
+ return 0;
+}
+
+static void iommu_group_free_blocking_domain(struct iommu_group *group,
+ struct device *dev)
+{
+ struct iommu_domain *domain = group->blocking_domain;
+
+ if (domain->type == IOMMU_DOMAIN_BLOCKED)
+ kfree(domain);
+ else
+ iommu_domain_free(domain);
+
+ group->blocking_domain = NULL;
+}
+
/**
* iommu_group_add_device - add a device to an iommu group
* @group: the group into which to add the device (reference should be held)
@@ -867,6 +905,12 @@ int iommu_group_add_device(struct iommu_group *group, struct device *dev)
int ret, i = 0;
struct group_device *device;

+ mutex_lock(&group->mutex);
+ ret = iommu_group_alloc_blocking_domain(group, dev);
+ mutex_unlock(&group->mutex);
+ if (ret)
+ return -ENODEV;
+
device = kzalloc(sizeof(*device), GFP_KERNEL);
if (!device)
return -ENOMEM;
@@ -961,6 +1005,8 @@ void iommu_group_remove_device(struct device *dev)
break;
}
}
+ if (list_empty(&group->devices))
+ iommu_group_free_blocking_domain(group, dev);
mutex_unlock(&group->mutex);

if (!device)
@@ -1961,12 +2007,16 @@ static void __iommu_group_set_core_domain(struct iommu_group *group)
static int __iommu_attach_device(struct iommu_domain *domain,
struct device *dev)
{
+ const struct iommu_domain_ops *ops = domain->ops;
int ret;

- if (unlikely(domain->ops->set_dev == NULL))
+ if (unlikely(ops->set_dev == NULL))
return -ENODEV;

- ret = domain->ops->set_dev(domain, dev);
+ if (domain->type == IOMMU_DOMAIN_BLOCKED)
+ domain = iommu_get_domain_for_dev(dev);
+
+ ret = ops->set_dev(domain, dev);
if (!ret)
trace_attach_device_to_domain(dev);
return ret;
@@ -3146,29 +3196,6 @@ void iommu_device_unuse_default_domain(struct device *dev)
iommu_group_put(group);
}

-static int __iommu_group_alloc_blocking_domain(struct iommu_group *group)
-{
- struct group_device *dev =
- list_first_entry(&group->devices, struct group_device, list);
-
- if (group->blocking_domain)
- return 0;
-
- group->blocking_domain =
- __iommu_domain_alloc(dev->dev->bus, IOMMU_DOMAIN_BLOCKED);
- if (!group->blocking_domain) {
- /*
- * For drivers that do not yet understand IOMMU_DOMAIN_BLOCKED
- * create an empty domain instead.
- */
- group->blocking_domain = __iommu_domain_alloc(
- dev->dev->bus, IOMMU_DOMAIN_UNMANAGED);
- if (!group->blocking_domain)
- return -EINVAL;
- }
- return 0;
-}
-
/**
* iommu_group_claim_dma_owner() - Set DMA ownership of a group
* @group: The group.
@@ -3192,10 +3219,6 @@ int iommu_group_claim_dma_owner(struct iommu_group *group, void *owner)
goto unlock_out;
}

- ret = __iommu_group_alloc_blocking_domain(group);
- if (ret)
- goto unlock_out;
-
ret = __iommu_group_set_domain(group, group->blocking_domain);
if (ret)
goto unlock_out;
--
2.25.1


2022-05-17 02:51:53

by Lu Baolu

[permalink] [raw]
Subject: [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 <[email protected]>
---
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 = {
.iotlb_sync_map = apple_dart_iotlb_sync_map,
.iova_to_phys = apple_dart_iova_to_phys,
.free = apple_dart_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = apple_dart_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 7e7d9e0b7aee..4b0ec5bef63b 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2867,6 +2867,9 @@ static struct iommu_ops arm_smmu_ops = {
.iova_to_phys = arm_smmu_iova_to_phys,
.enable_nesting = arm_smmu_enable_nesting,
.free = arm_smmu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = arm_smmu_attach_dev,
}
};

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index c91d12b7e283..0723f7c97763 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -1606,6 +1606,9 @@ static struct iommu_ops arm_smmu_ops = {
.enable_nesting = arm_smmu_enable_nesting,
.set_pgtable_quirks = arm_smmu_set_pgtable_quirks,
.free = arm_smmu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = arm_smmu_attach_dev,
}
};

diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
index cf624bd305e0..dee9b5a3a324 100644
--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
@@ -587,6 +587,14 @@ static int qcom_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
return iommu_fwspec_add_ids(dev, &asid, 1);
}

+static int qcom_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ qcom_iommu_detach_dev(domain, dev);
+
+ return 0;
+}
+
static const struct iommu_ops qcom_iommu_ops = {
.capable = qcom_iommu_capable,
.domain_alloc = qcom_iommu_domain_alloc,
@@ -604,6 +612,10 @@ static const struct iommu_ops qcom_iommu_ops = {
.iotlb_sync = qcom_iommu_iotlb_sync,
.iova_to_phys = qcom_iommu_iova_to_phys,
.free = qcom_iommu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = qcom_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 797348f3440e..bbecb9a2a554 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1307,6 +1307,14 @@ static int exynos_iommu_of_xlate(struct device *dev,
return 0;
}

+static int exynos_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ exynos_iommu_detach_device(domain, dev);
+
+ return 0;
+}
+
static const struct iommu_ops exynos_iommu_ops = {
.domain_alloc = exynos_iommu_domain_alloc,
.device_group = generic_device_group,
@@ -1321,6 +1329,10 @@ static const struct iommu_ops exynos_iommu_ops = {
.unmap = exynos_iommu_unmap,
.iova_to_phys = exynos_iommu_iova_to_phys,
.free = exynos_iommu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = exynos_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index 7512c8e007e9..92fc320f8c83 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -451,6 +451,14 @@ static void fsl_pamu_release_device(struct device *dev)
{
}

+static int fsl_pamu_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ fsl_pamu_detach_device(domain, dev);
+
+ return 0;
+}
+
static const struct iommu_ops fsl_pamu_ops = {
.capable = fsl_pamu_capable,
.domain_alloc = fsl_pamu_domain_alloc,
@@ -462,6 +470,10 @@ static const struct iommu_ops fsl_pamu_ops = {
.detach_dev = fsl_pamu_detach_device,
.iova_to_phys = fsl_pamu_iova_to_phys,
.free = fsl_pamu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = fsl_pamu_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 6abc1fbbd461..2060e8a540b3 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -4904,6 +4904,14 @@ static void intel_iommu_iotlb_sync_map(struct iommu_domain *domain,
}
}

+static int intel_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ intel_iommu_detach_device(domain, dev);
+
+ return 0;
+}
+
const struct iommu_ops intel_iommu_ops = {
.capable = intel_iommu_capable,
.domain_alloc = intel_iommu_domain_alloc,
@@ -4935,6 +4943,10 @@ const struct iommu_ops intel_iommu_ops = {
.iova_to_phys = intel_iommu_iova_to_phys,
.free = intel_iommu_domain_free,
.enforce_cache_coherency = intel_iommu_enforce_cache_coherency,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = intel_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index b361a4cff688..72982d1277c2 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -867,6 +867,14 @@ static struct iommu_group *ipmmu_find_group(struct device *dev)
return group;
}

+static int ipmmu_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ ipmmu_detach_device(domain, dev);
+
+ return 0;
+}
+
static const struct iommu_ops ipmmu_ops = {
.domain_alloc = ipmmu_domain_alloc,
.probe_device = ipmmu_probe_device,
@@ -885,6 +893,10 @@ static const struct iommu_ops ipmmu_ops = {
.iotlb_sync = ipmmu_iotlb_sync,
.iova_to_phys = ipmmu_iova_to_phys,
.free = ipmmu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = ipmmu_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 569d36840b67..b0471d03db60 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -674,6 +674,14 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
return 0;
}

+static int msm_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ msm_iommu_detach_dev(domain, dev);
+
+ return 0;
+}
+
static struct iommu_ops msm_iommu_ops = {
.domain_alloc = msm_iommu_domain_alloc,
.probe_device = msm_iommu_probe_device,
@@ -696,6 +704,10 @@ static struct iommu_ops msm_iommu_ops = {
.iotlb_sync_map = msm_iommu_sync_map,
.iova_to_phys = msm_iommu_iova_to_phys,
.free = msm_iommu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = msm_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 33ec401d40eb..cc8d80290498 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -926,6 +926,14 @@ static void mtk_iommu_get_resv_regions(struct device *dev,
}
}

+static int mtk_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ mtk_iommu_detach_device(domain, dev);
+
+ return 0;
+}
+
static const struct iommu_ops mtk_iommu_ops = {
.domain_alloc = mtk_iommu_domain_alloc,
.probe_device = mtk_iommu_probe_device,
@@ -946,6 +954,10 @@ static const struct iommu_ops mtk_iommu_ops = {
.iotlb_sync_map = mtk_iommu_sync_map,
.iova_to_phys = mtk_iommu_iova_to_phys,
.free = mtk_iommu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = mtk_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index fb55802fb841..894d2526ba4c 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -584,6 +584,14 @@ static int mtk_iommu_v1_hw_init(const struct mtk_iommu_v1_data *data)
return 0;
}

+static int mtk_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ mtk_iommu_v1_detach_device(domain, dev);
+
+ return 0;
+}
+
static const struct iommu_ops mtk_iommu_v1_ops = {
.domain_alloc = mtk_iommu_v1_domain_alloc,
.probe_device = mtk_iommu_v1_probe_device,
@@ -600,6 +608,10 @@ static const struct iommu_ops mtk_iommu_v1_ops = {
.unmap = mtk_iommu_v1_unmap,
.iova_to_phys = mtk_iommu_v1_iova_to_phys,
.free = mtk_iommu_v1_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = mtk_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 6720dcb437a0..7e6ba6f1218d 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1732,6 +1732,14 @@ static struct iommu_group *omap_iommu_device_group(struct device *dev)
return group;
}

+static int omap_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ omap_iommu_detach_dev(domain, dev);
+
+ return 0;
+}
+
static const struct iommu_ops omap_iommu_ops = {
.domain_alloc = omap_iommu_domain_alloc,
.probe_device = omap_iommu_probe_device,
@@ -1745,6 +1753,10 @@ static const struct iommu_ops omap_iommu_ops = {
.unmap = omap_iommu_unmap,
.iova_to_phys = omap_iommu_iova_to_phys,
.free = omap_iommu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = omap_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 0a4196c34179..29c803759a0b 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1185,6 +1185,14 @@ static int rk_iommu_of_xlate(struct device *dev,
return 0;
}

+static int rk_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ rk_iommu_detach_device(domain, dev);
+
+ return 0;
+}
+
static const struct iommu_ops rk_iommu_ops = {
.domain_alloc = rk_iommu_domain_alloc,
.probe_device = rk_iommu_probe_device,
@@ -1199,6 +1207,10 @@ static const struct iommu_ops rk_iommu_ops = {
.unmap = rk_iommu_unmap,
.iova_to_phys = rk_iommu_iova_to_phys,
.free = rk_iommu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = rk_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c
index cde01c72f573..a03bff562a44 100644
--- a/drivers/iommu/s390-iommu.c
+++ b/drivers/iommu/s390-iommu.c
@@ -360,6 +360,14 @@ void zpci_destroy_iommu(struct zpci_dev *zdev)
iommu_device_sysfs_remove(&zdev->iommu_dev);
}

+static int s390_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ s390_iommu_detach_device(domain, dev);
+
+ return 0;
+}
+
static const struct iommu_ops s390_iommu_ops = {
.capable = s390_iommu_capable,
.domain_alloc = s390_domain_alloc,
@@ -374,6 +382,10 @@ static const struct iommu_ops s390_iommu_ops = {
.unmap = s390_iommu_unmap,
.iova_to_phys = s390_iommu_iova_to_phys,
.free = s390_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = s390_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/sprd-iommu.c b/drivers/iommu/sprd-iommu.c
index 45b58845f5f8..ab62063cee5b 100644
--- a/drivers/iommu/sprd-iommu.c
+++ b/drivers/iommu/sprd-iommu.c
@@ -413,6 +413,13 @@ static int sprd_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
return 0;
}

+static int sprd_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ sprd_iommu_detach_device(domain, dev);
+
+ return 0;
+}

static const struct iommu_ops sprd_iommu_ops = {
.domain_alloc = sprd_iommu_domain_alloc,
@@ -431,6 +438,10 @@ static const struct iommu_ops sprd_iommu_ops = {
.iotlb_sync = sprd_iommu_sync,
.iova_to_phys = sprd_iommu_iova_to_phys,
.free = sprd_iommu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = sprd_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
index 041b30463552..a51a55ae0634 100644
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -758,6 +758,14 @@ static int sun50i_iommu_of_xlate(struct device *dev,
return iommu_fwspec_add_ids(dev, &id, 1);
}

+static int sun50i_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ sun50i_iommu_detach_device(domain, dev);
+
+ return 0;
+}
+
static const struct iommu_ops sun50i_iommu_ops = {
.pgsize_bitmap = SZ_4K,
.device_group = sun50i_iommu_device_group,
@@ -774,6 +782,10 @@ static const struct iommu_ops sun50i_iommu_ops = {
.map = sun50i_iommu_map,
.unmap = sun50i_iommu_unmap,
.free = sun50i_iommu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = sun50i_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c
index f083a9fba4d0..7e2aef7ae72e 100644
--- a/drivers/iommu/tegra-gart.c
+++ b/drivers/iommu/tegra-gart.c
@@ -270,6 +270,14 @@ static void gart_iommu_sync(struct iommu_domain *domain,
gart_iommu_sync_map(domain, gather->start, length);
}

+static int gart_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ gart_iommu_detach_dev(domain, dev);
+
+ return 0;
+}
+
static const struct iommu_ops gart_iommu_ops = {
.domain_alloc = gart_iommu_domain_alloc,
.probe_device = gart_iommu_probe_device,
@@ -286,6 +294,10 @@ static const struct iommu_ops gart_iommu_ops = {
.iotlb_sync_map = gart_iommu_sync_map,
.iotlb_sync = gart_iommu_sync,
.free = gart_iommu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = gart_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 36e9c2864e3f..fe2c463db230 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -963,6 +963,14 @@ static int tegra_smmu_of_xlate(struct device *dev,
return iommu_fwspec_add_ids(dev, &id, 1);
}

+static int tegra_smmu_blocking_domain_set_dev(struct iommu_domain *domain,
+ struct device *dev)
+{
+ tegra_smmu_detach_dev(domain, dev);
+
+ return 0;
+}
+
static const struct iommu_ops tegra_smmu_ops = {
.domain_alloc = tegra_smmu_domain_alloc,
.probe_device = tegra_smmu_probe_device,
@@ -977,6 +985,10 @@ static const struct iommu_ops tegra_smmu_ops = {
.unmap = tegra_smmu_unmap,
.iova_to_phys = tegra_smmu_iova_to_phys,
.free = tegra_smmu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = tegra_smmu_blocking_domain_set_dev,
+ .blocking_domain_detach = true,
}
};

diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index ce2bd01806d8..5054ebaf9654 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -1023,6 +1023,9 @@ static struct iommu_ops viommu_ops = {
.iova_to_phys = viommu_iova_to_phys,
.iotlb_sync = viommu_iotlb_sync,
.free = viommu_domain_free,
+ },
+ .blocking_domain_ops = &(const struct iommu_domain_ops) {
+ .set_dev = viommu_attach_dev,
}
};

--
2.25.1


2022-05-17 03:33:43

by Lu Baolu

[permalink] [raw]
Subject: 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

2022-05-17 03:39:16

by Robin Murphy

[permalink] [raw]
Subject: 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 <[email protected]>
> ---
> 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 = {
> .iotlb_sync_map = apple_dart_iotlb_sync_map,
> .iova_to_phys = apple_dart_iova_to_phys,
> .free = apple_dart_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = apple_dart_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index 7e7d9e0b7aee..4b0ec5bef63b 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -2867,6 +2867,9 @@ static struct iommu_ops arm_smmu_ops = {
> .iova_to_phys = arm_smmu_iova_to_phys,
> .enable_nesting = arm_smmu_enable_nesting,
> .free = arm_smmu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = arm_smmu_attach_dev,
> }
> };
>
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index c91d12b7e283..0723f7c97763 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -1606,6 +1606,9 @@ static struct iommu_ops arm_smmu_ops = {
> .enable_nesting = arm_smmu_enable_nesting,
> .set_pgtable_quirks = arm_smmu_set_pgtable_quirks,
> .free = arm_smmu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = arm_smmu_attach_dev,
> }
> };
>
> diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
> index cf624bd305e0..dee9b5a3a324 100644
> --- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
> +++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
> @@ -587,6 +587,14 @@ static int qcom_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
> return iommu_fwspec_add_ids(dev, &asid, 1);
> }
>
> +static int qcom_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + qcom_iommu_detach_dev(domain, dev);
> +
> + return 0;
> +}
> +
> static const struct iommu_ops qcom_iommu_ops = {
> .capable = qcom_iommu_capable,
> .domain_alloc = qcom_iommu_domain_alloc,
> @@ -604,6 +612,10 @@ static const struct iommu_ops qcom_iommu_ops = {
> .iotlb_sync = qcom_iommu_iotlb_sync,
> .iova_to_phys = qcom_iommu_iova_to_phys,
> .free = qcom_iommu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = qcom_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
> index 797348f3440e..bbecb9a2a554 100644
> --- a/drivers/iommu/exynos-iommu.c
> +++ b/drivers/iommu/exynos-iommu.c
> @@ -1307,6 +1307,14 @@ static int exynos_iommu_of_xlate(struct device *dev,
> return 0;
> }
>
> +static int exynos_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + exynos_iommu_detach_device(domain, dev);
> +
> + return 0;
> +}
> +
> static const struct iommu_ops exynos_iommu_ops = {
> .domain_alloc = exynos_iommu_domain_alloc,
> .device_group = generic_device_group,
> @@ -1321,6 +1329,10 @@ static const struct iommu_ops exynos_iommu_ops = {
> .unmap = exynos_iommu_unmap,
> .iova_to_phys = exynos_iommu_iova_to_phys,
> .free = exynos_iommu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = exynos_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
> index 7512c8e007e9..92fc320f8c83 100644
> --- a/drivers/iommu/fsl_pamu_domain.c
> +++ b/drivers/iommu/fsl_pamu_domain.c
> @@ -451,6 +451,14 @@ static void fsl_pamu_release_device(struct device *dev)
> {
> }
>
> +static int fsl_pamu_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + fsl_pamu_detach_device(domain, dev);
> +
> + return 0;
> +}
> +
> static const struct iommu_ops fsl_pamu_ops = {
> .capable = fsl_pamu_capable,
> .domain_alloc = fsl_pamu_domain_alloc,
> @@ -462,6 +470,10 @@ static const struct iommu_ops fsl_pamu_ops = {
> .detach_dev = fsl_pamu_detach_device,
> .iova_to_phys = fsl_pamu_iova_to_phys,
> .free = fsl_pamu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = fsl_pamu_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index 6abc1fbbd461..2060e8a540b3 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -4904,6 +4904,14 @@ static void intel_iommu_iotlb_sync_map(struct iommu_domain *domain,
> }
> }
>
> +static int intel_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + intel_iommu_detach_device(domain, dev);
> +
> + return 0;
> +}
> +
> const struct iommu_ops intel_iommu_ops = {
> .capable = intel_iommu_capable,
> .domain_alloc = intel_iommu_domain_alloc,
> @@ -4935,6 +4943,10 @@ const struct iommu_ops intel_iommu_ops = {
> .iova_to_phys = intel_iommu_iova_to_phys,
> .free = intel_iommu_domain_free,
> .enforce_cache_coherency = intel_iommu_enforce_cache_coherency,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = intel_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
> index b361a4cff688..72982d1277c2 100644
> --- a/drivers/iommu/ipmmu-vmsa.c
> +++ b/drivers/iommu/ipmmu-vmsa.c
> @@ -867,6 +867,14 @@ static struct iommu_group *ipmmu_find_group(struct device *dev)
> return group;
> }
>
> +static int ipmmu_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + ipmmu_detach_device(domain, dev);
> +
> + return 0;
> +}
> +
> static const struct iommu_ops ipmmu_ops = {
> .domain_alloc = ipmmu_domain_alloc,
> .probe_device = ipmmu_probe_device,
> @@ -885,6 +893,10 @@ static const struct iommu_ops ipmmu_ops = {
> .iotlb_sync = ipmmu_iotlb_sync,
> .iova_to_phys = ipmmu_iova_to_phys,
> .free = ipmmu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = ipmmu_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
> index 569d36840b67..b0471d03db60 100644
> --- a/drivers/iommu/msm_iommu.c
> +++ b/drivers/iommu/msm_iommu.c
> @@ -674,6 +674,14 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
> return 0;
> }
>
> +static int msm_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + msm_iommu_detach_dev(domain, dev);
> +
> + return 0;
> +}
> +
> static struct iommu_ops msm_iommu_ops = {
> .domain_alloc = msm_iommu_domain_alloc,
> .probe_device = msm_iommu_probe_device,
> @@ -696,6 +704,10 @@ static struct iommu_ops msm_iommu_ops = {
> .iotlb_sync_map = msm_iommu_sync_map,
> .iova_to_phys = msm_iommu_iova_to_phys,
> .free = msm_iommu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = msm_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 33ec401d40eb..cc8d80290498 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -926,6 +926,14 @@ static void mtk_iommu_get_resv_regions(struct device *dev,
> }
> }
>
> +static int mtk_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + mtk_iommu_detach_device(domain, dev);
> +
> + return 0;
> +}
> +
> static const struct iommu_ops mtk_iommu_ops = {
> .domain_alloc = mtk_iommu_domain_alloc,
> .probe_device = mtk_iommu_probe_device,
> @@ -946,6 +954,10 @@ static const struct iommu_ops mtk_iommu_ops = {
> .iotlb_sync_map = mtk_iommu_sync_map,
> .iova_to_phys = mtk_iommu_iova_to_phys,
> .free = mtk_iommu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = mtk_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
> index fb55802fb841..894d2526ba4c 100644
> --- a/drivers/iommu/mtk_iommu_v1.c
> +++ b/drivers/iommu/mtk_iommu_v1.c
> @@ -584,6 +584,14 @@ static int mtk_iommu_v1_hw_init(const struct mtk_iommu_v1_data *data)
> return 0;
> }
>
> +static int mtk_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + mtk_iommu_v1_detach_device(domain, dev);
> +
> + return 0;
> +}
> +
> static const struct iommu_ops mtk_iommu_v1_ops = {
> .domain_alloc = mtk_iommu_v1_domain_alloc,
> .probe_device = mtk_iommu_v1_probe_device,
> @@ -600,6 +608,10 @@ static const struct iommu_ops mtk_iommu_v1_ops = {
> .unmap = mtk_iommu_v1_unmap,
> .iova_to_phys = mtk_iommu_v1_iova_to_phys,
> .free = mtk_iommu_v1_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = mtk_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
> index 6720dcb437a0..7e6ba6f1218d 100644
> --- a/drivers/iommu/omap-iommu.c
> +++ b/drivers/iommu/omap-iommu.c
> @@ -1732,6 +1732,14 @@ static struct iommu_group *omap_iommu_device_group(struct device *dev)
> return group;
> }
>
> +static int omap_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + omap_iommu_detach_dev(domain, dev);
> +
> + return 0;
> +}
> +
> static const struct iommu_ops omap_iommu_ops = {
> .domain_alloc = omap_iommu_domain_alloc,
> .probe_device = omap_iommu_probe_device,
> @@ -1745,6 +1753,10 @@ static const struct iommu_ops omap_iommu_ops = {
> .unmap = omap_iommu_unmap,
> .iova_to_phys = omap_iommu_iova_to_phys,
> .free = omap_iommu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = omap_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
> index 0a4196c34179..29c803759a0b 100644
> --- a/drivers/iommu/rockchip-iommu.c
> +++ b/drivers/iommu/rockchip-iommu.c
> @@ -1185,6 +1185,14 @@ static int rk_iommu_of_xlate(struct device *dev,
> return 0;
> }
>
> +static int rk_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + rk_iommu_detach_device(domain, dev);
> +
> + return 0;
> +}
> +
> static const struct iommu_ops rk_iommu_ops = {
> .domain_alloc = rk_iommu_domain_alloc,
> .probe_device = rk_iommu_probe_device,
> @@ -1199,6 +1207,10 @@ static const struct iommu_ops rk_iommu_ops = {
> .unmap = rk_iommu_unmap,
> .iova_to_phys = rk_iommu_iova_to_phys,
> .free = rk_iommu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = rk_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c
> index cde01c72f573..a03bff562a44 100644
> --- a/drivers/iommu/s390-iommu.c
> +++ b/drivers/iommu/s390-iommu.c
> @@ -360,6 +360,14 @@ void zpci_destroy_iommu(struct zpci_dev *zdev)
> iommu_device_sysfs_remove(&zdev->iommu_dev);
> }
>
> +static int s390_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + s390_iommu_detach_device(domain, dev);
> +
> + return 0;
> +}
> +
> static const struct iommu_ops s390_iommu_ops = {
> .capable = s390_iommu_capable,
> .domain_alloc = s390_domain_alloc,
> @@ -374,6 +382,10 @@ static const struct iommu_ops s390_iommu_ops = {
> .unmap = s390_iommu_unmap,
> .iova_to_phys = s390_iommu_iova_to_phys,
> .free = s390_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = s390_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/sprd-iommu.c b/drivers/iommu/sprd-iommu.c
> index 45b58845f5f8..ab62063cee5b 100644
> --- a/drivers/iommu/sprd-iommu.c
> +++ b/drivers/iommu/sprd-iommu.c
> @@ -413,6 +413,13 @@ static int sprd_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
> return 0;
> }
>
> +static int sprd_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + sprd_iommu_detach_device(domain, dev);
> +
> + return 0;
> +}
>
> static const struct iommu_ops sprd_iommu_ops = {
> .domain_alloc = sprd_iommu_domain_alloc,
> @@ -431,6 +438,10 @@ static const struct iommu_ops sprd_iommu_ops = {
> .iotlb_sync = sprd_iommu_sync,
> .iova_to_phys = sprd_iommu_iova_to_phys,
> .free = sprd_iommu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = sprd_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
> index 041b30463552..a51a55ae0634 100644
> --- a/drivers/iommu/sun50i-iommu.c
> +++ b/drivers/iommu/sun50i-iommu.c
> @@ -758,6 +758,14 @@ static int sun50i_iommu_of_xlate(struct device *dev,
> return iommu_fwspec_add_ids(dev, &id, 1);
> }
>
> +static int sun50i_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + sun50i_iommu_detach_device(domain, dev);
> +
> + return 0;
> +}
> +
> static const struct iommu_ops sun50i_iommu_ops = {
> .pgsize_bitmap = SZ_4K,
> .device_group = sun50i_iommu_device_group,
> @@ -774,6 +782,10 @@ static const struct iommu_ops sun50i_iommu_ops = {
> .map = sun50i_iommu_map,
> .unmap = sun50i_iommu_unmap,
> .free = sun50i_iommu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = sun50i_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c
> index f083a9fba4d0..7e2aef7ae72e 100644
> --- a/drivers/iommu/tegra-gart.c
> +++ b/drivers/iommu/tegra-gart.c
> @@ -270,6 +270,14 @@ static void gart_iommu_sync(struct iommu_domain *domain,
> gart_iommu_sync_map(domain, gather->start, length);
> }
>
> +static int gart_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + gart_iommu_detach_dev(domain, dev);
> +
> + return 0;
> +}
> +
> static const struct iommu_ops gart_iommu_ops = {
> .domain_alloc = gart_iommu_domain_alloc,
> .probe_device = gart_iommu_probe_device,
> @@ -286,6 +294,10 @@ static const struct iommu_ops gart_iommu_ops = {
> .iotlb_sync_map = gart_iommu_sync_map,
> .iotlb_sync = gart_iommu_sync,
> .free = gart_iommu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = gart_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
> index 36e9c2864e3f..fe2c463db230 100644
> --- a/drivers/iommu/tegra-smmu.c
> +++ b/drivers/iommu/tegra-smmu.c
> @@ -963,6 +963,14 @@ static int tegra_smmu_of_xlate(struct device *dev,
> return iommu_fwspec_add_ids(dev, &id, 1);
> }
>
> +static int tegra_smmu_blocking_domain_set_dev(struct iommu_domain *domain,
> + struct device *dev)
> +{
> + tegra_smmu_detach_dev(domain, dev);
> +
> + return 0;
> +}
> +
> static const struct iommu_ops tegra_smmu_ops = {
> .domain_alloc = tegra_smmu_domain_alloc,
> .probe_device = tegra_smmu_probe_device,
> @@ -977,6 +985,10 @@ static const struct iommu_ops tegra_smmu_ops = {
> .unmap = tegra_smmu_unmap,
> .iova_to_phys = tegra_smmu_iova_to_phys,
> .free = tegra_smmu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = tegra_smmu_blocking_domain_set_dev,
> + .blocking_domain_detach = true,
> }
> };
>
> diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
> index ce2bd01806d8..5054ebaf9654 100644
> --- a/drivers/iommu/virtio-iommu.c
> +++ b/drivers/iommu/virtio-iommu.c
> @@ -1023,6 +1023,9 @@ static struct iommu_ops viommu_ops = {
> .iova_to_phys = viommu_iova_to_phys,
> .iotlb_sync = viommu_iotlb_sync,
> .free = viommu_domain_free,
> + },
> + .blocking_domain_ops = &(const struct iommu_domain_ops) {
> + .set_dev = viommu_attach_dev,
> }
> };
>

2022-05-20 22:47:25

by Joerg Roedel

[permalink] [raw]
Subject: 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

2022-05-23 07:22:36

by Lu Baolu

[permalink] [raw]
Subject: 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