> -----Original Message-----
> From: Joerg Roedel <j...@8bytes.org>
> Sent: Friday, May 15, 2020 8:46 AM
> To: Lu Baolu <baolu...@linux.intel.com>
> Cc: Prakhya, Sai Praneeth <sai.praneeth.prak...@intel.com>;
> iommu@lists.linux-foundation.org
> Subject: Re: [PATCH] iommu: Remove functions that support private domain
> 
> On Fri, May 15, 2020 at 08:55:42PM +0800, Lu Baolu wrote:
> > It seems that we can do like this:
> >
> > [1] mutex_lock(&group->lock)
> > [2] for_each_group_device(device_lock())
> > [3] if (for_each_group_device(!device_is_bound()))
> >     change_default_domain()
> > [4] for_each_group_device_reverse(device_unlock())
> > [5] mutex_unlock(&group->lock)

>> A possible problem exists at step 2 when another thread is trying to lock 
>> devices in the reverse order at the same time. -> By Allen

Makes sense.. this could happen and we could prevent this if the iommu_group 
has only one device. So, going with Joerg's suggestion, if we support dynamic 
switching of default-domain of a group with only one device, I think we 
shouldn't hit this issue.

> The problem here is that I am pretty sure we also have:
> 
>       device_lock() /* from device/driver core code */
>       -> bus_notifier()
>         -> iommu_bus_notifier()
>           -> ...
>             -> mutex_lock(&group->lock)
> 
> Which would cause lock-inversion with the above code.

Thanks for this call chain, Joerg. It makes sense to me how lock inversion 
could happen

iommu_bus_notifier()
-> iommu_release_device()
 -> ops->release_device() (Eg: intel_iommu_release_device())
  -> iommu_group_remove_device()
   -> mutex_lock()

But, I added print statements to iommu_bus_notifier() and 
iommu_group_remove_device() and noticed that iommu_group_remove_device() wasn't 
being called upon modprobe -r <driver_name> and iommu_probe_device() isn't 
called upon modprobe <driver_name> because

        if (action == BUS_NOTIFY_ADD_DEVICE) {
                int ret;

                ret = iommu_probe_device(dev);
                return (ret) ? NOTIFY_DONE : NOTIFY_OK;
        } else if (action == BUS_NOTIFY_REMOVED_DEVICE) {
                iommu_release_device(dev);
                return NOTIFY_OK;
        }

"action" was != BUS_NOTIFY_ADD_DEVICE || BUS_NOTIFY_REMOVED_DEVICE upon 
modprobe. So (after booting [1]), I am wondering when would action be == to one 
of the above so that these iommu functions get called.

And,
        switch (action) {
        case BUS_NOTIFY_BIND_DRIVER:
                group_action = IOMMU_GROUP_NOTIFY_BIND_DRIVER;
                break;
        case BUS_NOTIFY_BOUND_DRIVER:
                group_action = IOMMU_GROUP_NOTIFY_BOUND_DRIVER;
                break;
        case BUS_NOTIFY_UNBIND_DRIVER:
                group_action = IOMMU_GROUP_NOTIFY_UNBIND_DRIVER;
                break;
        case BUS_NOTIFY_UNBOUND_DRIVER:
                group_action = IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER;
                break;
        }

        if (group_action)
                blocking_notifier_call_chain(&group->notifier,
                                             group_action, dev);

I also noticed that vfio is the only one that registers for group notifiers and 
from a first look it wasn't very obvious if vfio is trying to get group->mutex.

[1] I am interested in after booting because dynamic switching of iommu_group 
default-domain is supported only through sysfs.

Regards,
Sai
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to