RE: [RFC 14/20] iommu/iommufd: Add iommufd_device_[de]attach_ioasid()

Tian, Kevin
2021-09-22T03:56:10Z

> From: Jason Gunthorpe <jgg@nvidia.com>
> Sent: Wednesday, September 22, 2021 2:02 AM
>
> > +static int ioas_check_device_compatibility(struct iommufd_ioas *ioas,
> > + struct device *dev)
> > +{
> > + bool snoop = false;
> > + u32 addr_width;
> > + int ret;
> > +
> > + /*
> > + * currently we only support I/O page table with iommu enforce-
> snoop
> > + * format. Attaching a device which doesn't support this format in its
> > + * upstreaming iommu is rejected.
> > + */
> > + ret = iommu_device_get_info(dev,
> IOMMU_DEV_INFO_FORCE_SNOOP, &snoop);
> > + if (ret || !snoop)
> > + return -EINVAL;
> > +
> > + ret = iommu_device_get_info(dev,
> IOMMU_DEV_INFO_ADDR_WIDTH, &addr_width);
> > + if (ret || addr_width < ioas->addr_width)
> > + return -EINVAL;
> > +
> > + /* TODO: also need to check permitted iova ranges and pgsize
> bitmap */
> > +
> > + return 0;
> > +}
>
> This seems kind of weird..
>
> I expect the iommufd to hold a SW copy of the IO page table and each
> time a new domain is to be created it should push the SW copy into the
> domain. If the domain cannot support it then the domain driver should
> naturally fail a request.
>
> When the user changes the IO page table the SW copy is updated then
> all of the domains are updated too - again if any domain cannot
> support the change then it fails and the change is rolled back.
>
> It seems like this is a side effect of roughly hacking in the vfio
> code?

Actually this was one open we closed in previous design proposal, but
looks you have a different thought now.

vfio maintains one ioas per container. Devices in the container
can be attached to different domains (e.g. due to snoop format). Every
time when the ioas is updated, every attached domain is updated
in accordance.

You recommended one-ioas-one-domain model instead, i.e. any device
with a format incompatible with the one currently used in ioas has to
be attached to a new ioas, even if the two ioas's have the same mapping.
This leads to compatibility check at attaching time.

Now you want returning back to the vfio model?

>
> > + /*
> > + * Each ioas is backed by an iommu domain, which is allocated
> > + * when the ioas is attached for the first time and then shared
> > + * by following devices.
> > + */
> > + if (list_empty(&ioas->device_list)) {
>
> Seems strange, what if the devices are forced to have different
> domains? We don't want to model that in the SW layer..

this is due to above background

>
> > + /* Install the I/O page table to the iommu for this device */
> > + ret = iommu_attach_device(domain, idev->dev);
> > + if (ret)
> > + goto out_domain;
>
> This is where things start to get confusing when you talk about PASID
> as the above call needs to be some PASID centric API.

yes, for pasid new api (e.g. iommu_attach_device_pasid()) will be added.

but here we only talk about physical device, and iommu_attach_device()
is only for physical device.

>
> > @@ -27,6 +28,16 @@ struct iommufd_device *
> > iommufd_bind_device(int fd, struct device *dev, u64 dev_cookie);
> > void iommufd_unbind_device(struct iommufd_device *idev);
> >
> > +int iommufd_device_attach_ioasid(struct iommufd_device *idev, int
> ioasid);
> > +void iommufd_device_detach_ioasid(struct iommufd_device *idev, int
> ioasid);
> > +
> > +static inline int
> > +__pci_iommufd_device_attach_ioasid(struct pci_dev *pdev,
> > + struct iommufd_device *idev, int ioasid)
> > +{
> > + return iommufd_device_attach_ioasid(idev, ioasid);
> > +}
>
> If think sis taking in the iommfd_device then there isn't a logical
> place to signal the PCIness

can you elaborate?

>
> But, I think the API should at least have a kdoc that this is
> capturing the entire device and specify that for PCI this means all
> TLPs with the RID.
>

yes, this should be documented.