The normal domain at(de)tach is parallel with aux-domain at(de)tach. In another word, once an iommu_group is attached through the normal domain attach api's, it should not go through the aux-domain at(de)tach api's until the domain is detached. And, vice versa. Currently, we prohibit an iommu_group to go through aux-domain api's if group->domain != NULL; but we don't check aux-domain attachment in the normal attach api's. This marks an iommu_group after an aux-domain is attached, so that normal domain at(de)tach api's should never be used after that. Cc: Robin Murphy <robin.murphy@xxxxxxx> Signed-off-by: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx> --- drivers/iommu/iommu.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 435835058209..3e7489ea2010 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -45,6 +45,7 @@ struct iommu_group { struct iommu_domain *default_domain; struct iommu_domain *domain; struct list_head entry; + unsigned int aux_domain_attached:1; }; struct group_device { @@ -2074,6 +2075,9 @@ static int __iommu_attach_group(struct iommu_domain *domain, { int ret; + if (group->aux_domain_attached) + return -EINVAL; + if (group->default_domain && group->domain != group->default_domain) return -EBUSY; @@ -2111,6 +2115,9 @@ static void __iommu_detach_group(struct iommu_domain *domain, { int ret; + if (WARN_ON(group->aux_domain_attached)) + return; + if (!group->default_domain) { __iommu_group_for_each_dev(group, domain, iommu_group_do_detach_device); @@ -2769,6 +2776,7 @@ int iommu_aux_attach_device(struct iommu_domain *domain, if (!ret) { trace_attach_device_to_domain(phys_dev); group->domain = domain; + group->aux_domain_attached = true; } out_unlock: @@ -2802,8 +2810,12 @@ void iommu_aux_detach_device(struct iommu_domain *domain, if (WARN_ON(iommu_group_device_count(group) != 1)) goto out_unlock; + if (WARN_ON(!group->aux_domain_attached)) + goto out_unlock; + domain->ops->aux_detach_dev(domain, phys_dev); group->domain = NULL; + group->aux_domain_attached = false; trace_detach_device_from_domain(phys_dev); out_unlock: -- 2.17.1