Message ID | 8-v1-7612f88c19f5+2f21-iommufd_alloc_jgg@nvidia.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Add iommufd physical device operations for replace and alloc hwpt | expand |
> From: Jason Gunthorpe <jgg@nvidia.com> > Sent: Saturday, February 25, 2023 8:28 AM > > From: Nicolin Chen <nicolinc@nvidia.com> > > qemu has a need to replace the translations associated with a domain > when the guest does large-scale operations like switching between an > IDENTITY domain and, say, dma-iommu.c. > > Currently, it does this by replacing all the mappings in a single > domain, but this is very inefficient and means that domains have to be > per-device rather than per-translation. > > Provide a high-level API to allow replacements of one domain with > another. This is similar to a detach/attach cycle except it doesn't > force the group to go to the blocking domain in-between. > > By removing this forced blocking domain the iommu driver has the > opportunity to implement a non-disruptive replacement of the domain to the > greatest extent its hardware allows. This allows the qemu emulation of the > vIOMMU to be more complete, as real hardware often has a non-distruptive > replacement capability. > > It could be possible to adderss this by simply removing the protection > from the iommu_attach_group(), but it is not so clear if that is safe for > the few users. Thus, add a new API to serve this new purpose. > > All drivers are already required to support changing between active > UNMANAGED domains when using their attach_dev ops. > > This API is expected to be used only by IOMMUFD, so add to the iommu-priv > header and mark it as IOMMUFD_INTERNAL. > > Suggested-by: Jason Gunthorpe <jgg@nvidia.com> > Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> > Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
diff --git a/drivers/iommu/iommu-priv.h b/drivers/iommu/iommu-priv.h new file mode 100644 index 00000000000000..7c8011bfd15374 --- /dev/null +++ b/drivers/iommu/iommu-priv.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __LINUX_IOMMU_PRIV_H +#define __LINUX_IOMMU_PRIV_H + +#include <linux/iommu.h> + +int iommu_group_replace_domain(struct iommu_group *group, + struct iommu_domain *new_domain); + +#endif /* __LINUX_IOMMU_PRIV_H */ diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 10db680acaed5a..4c91d9bdd114ab 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -33,6 +33,7 @@ #include <linux/msi.h> #include "dma-iommu.h" +#include "iommu-priv.h" #include "iommu-sva.h" @@ -2191,6 +2192,35 @@ int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group) } EXPORT_SYMBOL_GPL(iommu_attach_group); +/** + * iommu_group_replace_domain - replace the domain that a group is attached to + * @new_domain: new IOMMU domain to replace with + * @group: IOMMU group that will be attached to the new domain + * + * This API allows the group to switch domains without being forced to go to + * the blocking domain in-between. + * + * If the currently attached domain is a core domain (e.g. a default_domain), + * it will act just like the iommu_attach_group(). + */ +int iommu_group_replace_domain(struct iommu_group *group, + struct iommu_domain *new_domain) +{ + int ret; + + if (!new_domain) + return -EINVAL; + + mutex_lock(&group->mutex); + ret = __iommu_group_set_domain(group, new_domain); + if (ret) + __iommu_group_for_each_dev(group, group->domain, + iommu_group_do_attach_device); + mutex_unlock(&group->mutex); + return ret; +} +EXPORT_SYMBOL_NS_GPL(iommu_group_replace_domain, IOMMUFD_INTERNAL); + static int iommu_group_do_set_platform_dma(struct device *dev, void *data) { const struct iommu_ops *ops = dev_iommu_ops(dev);