All of lore.kernel.org
 help / color / mirror / Atom feed
From: Baolu Lu <baolu.lu@linux.intel.com>
To: Jason Gunthorpe <jgg@nvidia.com>, "Tian, Kevin" <kevin.tian@intel.com>
Cc: baolu.lu@linux.intel.com, Joerg Roedel <joro@8bytes.org>,
	Christoph Hellwig <hch@infradead.org>,
	"Raj, Ashok" <ashok.raj@intel.com>, Will Deacon <will@kernel.org>,
	Robin Murphy <robin.murphy@arm.com>,
	Jean-Philippe Brucker <jean-philippe@linaro.com>,
	"Jiang, Dave" <dave.jiang@intel.com>,
	Vinod Koul <vkoul@kernel.org>, Eric Auger <eric.auger@redhat.com>,
	"Liu, Yi L" <yi.l.liu@intel.com>,
	"Pan, Jacob jun" <jacob.jun.pan@intel.com>,
	Zhangfei Gao <zhangfei.gao@linaro.org>,
	"Zhu, Tony" <tony.zhu@intel.com>,
	"iommu@lists.linux.dev" <iommu@lists.linux.dev>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	Jean-Philippe Brucker <jean-philippe@linaro.org>
Subject: Re: [PATCH v10 04/12] iommu: Add attach/detach_dev_pasid iommu interface
Date: Fri, 29 Jul 2022 10:49:04 +0800	[thread overview]
Message-ID: <78376ca4-9b55-7609-abf1-27a1a376a8e0@linux.intel.com> (raw)
In-Reply-To: <YuJ6MXoNTj0RKCb8@nvidia.com>

On 2022/7/28 19:59, Jason Gunthorpe wrote:
> On Thu, Jul 28, 2022 at 03:06:47AM +0000, Tian, Kevin wrote:
> 
>>> Then we don't need this weirdo check in the core iommu code at all.
>>
>> and then we could also move group->pasid_array to device->pasid_array
>> with this approach. Though the end result doesn't change i.e. still only
>> the singleton group can enable pasid the iommu core can just stick to
>> the device manner now.
> 
> I don't see why, the group is still logically the unit of attachment
> in the iommu area, and if we have a multi-device group it just means
> we iterate over all the devices in the group when doing pasid set, no
> different than a RID.

Okay. Based on the discussions in this thread, this patch will evolve to
look like below. Any comments or concerns?

[PATCH 04/12] iommu: Add attach/detach_dev_pasid iommu interface

Attaching an IOMMU domain to a PASID of a device is a generic operation
for modern IOMMU drivers which support PASID-granular DMA address
translation. Currently visible usage scenarios include (but not limited):

  - SVA (Shared Virtual Address)
  - kernel DMA with PASID
  - hardware-assist mediated device

This adds set_dev_pasid domain ops for this purpose and also adds some
interfaces for device drivers to attach/detach/retrieve a domain for a
PASID of a device.

Multiple devices in an iommu group cannot be isolated from each other,
then it's also difficult to ensure that their pasid address spaces are
isolated without any guarantee of hardware mechanism. To make things
simple, this starts the PASID attach/detach support from the devices
belonging to singleton groups.

Some configurations of the PCI fabric will route device originated TLP
packets based on the memory addresses. These configurations are
incompatible with PASID as the PASID packets form a distinct address
space. For instance, any configuration where switches are present
without ACS enabled is incompatible. In the future, we can further
discuss the possibility of moving this restriction into PCI subsystem
and making it a prerequisite of pci_enable_pasid().

[--tags removed --]

---
  include/linux/iommu.h |  26 ++++++++
  drivers/iommu/iommu.c | 146 ++++++++++++++++++++++++++++++++++++++++++
  2 files changed, 172 insertions(+)

diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 2f237c3cd680..f1e8953b1e2e 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -266,6 +266,7 @@ struct iommu_ops {
   * struct iommu_domain_ops - domain specific operations
   * @attach_dev: attach an iommu domain to a device
   * @detach_dev: detach an iommu domain from a device
+ * @set_dev_pasid: set an iommu domain to a pasid of 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.
@@ -286,6 +287,8 @@ struct iommu_ops {
  struct iommu_domain_ops {
  	int (*attach_dev)(struct iommu_domain *domain, struct device *dev);
  	void (*detach_dev)(struct iommu_domain *domain, struct device *dev);
+	int (*set_dev_pasid)(struct iommu_domain *domain, struct device *dev,
+			     ioasid_t pasid);

  	int (*map)(struct iommu_domain *domain, unsigned long iova,
  		   phys_addr_t paddr, size_t size, int prot, gfp_t gfp);
@@ -680,6 +683,12 @@ int iommu_group_claim_dma_owner(struct iommu_group 
*group, void *owner);
  void iommu_group_release_dma_owner(struct iommu_group *group);
  bool iommu_group_dma_owner_claimed(struct iommu_group *group);

+int iommu_attach_device_pasid(struct iommu_domain *domain,
+			      struct device *dev, ioasid_t pasid);
+void iommu_detach_device_pasid(struct iommu_domain *domain,
+			       struct device *dev, ioasid_t pasid);
+struct iommu_domain *
+iommu_get_domain_for_dev_pasid(struct device *dev, ioasid_t pasid);
  #else /* CONFIG_IOMMU_API */

  struct iommu_ops {};
@@ -1047,6 +1056,23 @@ static inline bool 
iommu_group_dma_owner_claimed(struct iommu_group *group)
  {
  	return false;
  }
+
+static inline int iommu_attach_device_pasid(struct iommu_domain *domain,
+					    struct device *dev, ioasid_t pasid)
+{
+	return -ENODEV;
+}
+
+static inline void iommu_detach_device_pasid(struct iommu_domain *domain,
+					     struct device *dev, ioasid_t pasid)
+{
+}
+
+static inline struct iommu_domain *
+iommu_get_domain_for_dev_pasid(struct device *dev, ioasid_t pasid)
+{
+	return NULL;
+}
  #endif /* CONFIG_IOMMU_API */

  /**
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 63fc4317cb47..46b8bffddc4d 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -39,6 +39,7 @@ struct iommu_group {
  	struct kobject kobj;
  	struct kobject *devices_kobj;
  	struct list_head devices;
+	struct xarray pasid_array;
  	struct mutex mutex;
  	void *iommu_data;
  	void (*iommu_data_release)(void *iommu_data);
@@ -663,6 +664,7 @@ struct iommu_group *iommu_group_alloc(void)
  	mutex_init(&group->mutex);
  	INIT_LIST_HEAD(&group->devices);
  	INIT_LIST_HEAD(&group->entry);
+	xa_init(&group->pasid_array);

  	ret = ida_alloc(&iommu_group_ida, GFP_KERNEL);
  	if (ret < 0) {
@@ -890,6 +892,14 @@ int iommu_group_add_device(struct iommu_group 
*group, struct device *dev)
  	int ret, i = 0;
  	struct group_device *device;

+	/*
+	 * The iommu_attach_device_pasid() requires a singleton group.
+	 * Refuse to add a device into it if this assumption has been
+	 * made.
+	 */
+	if (!xa_empty(&group->pasid_array))
+		return -EBUSY;
+
  	device = kzalloc(sizeof(*device), GFP_KERNEL);
  	if (!device)
  		return -ENOMEM;
@@ -3254,3 +3264,139 @@ bool iommu_group_dma_owner_claimed(struct 
iommu_group *group)
  	return user;
  }
  EXPORT_SYMBOL_GPL(iommu_group_dma_owner_claimed);
+
+/*
+ * Check the viability of PASID attach/detach on a @dev of a @group.
+ *
+ * Basically we don't support pasid attach/detach on multi-device groups.
+ * Multiple devices in an iommu group cannot be isolated from each other,
+ * then it's also difficult to ensure that their pasid address spaces are
+ * isolated without any guarantee of hardware mechanism. To make things
+ * simple, let's start the PASID attach/detach support from the devices
+ * belonging to singleton groups.
+ *
+ * Some configurations of the PCI fabric will route device originated TLP
+ * packets based on memory address, and these configurations are
+ * incompatible with PASID as the PASID packets form a distinct address
+ * space. For instance any configuration where switches are present
+ * without ACS enabled is incompatible.
+ */
+static bool iommu_group_device_pasid_viable(struct iommu_group *group,
+					    struct device *dev)
+{
+	int count;
+
+	count = iommu_group_device_count(group);
+	if (count != 1)
+		return false;
+
+	/*
+	 * Block PASID attachment in cases where the PCI fabric is
+	 * routing based on address. PCI/ACS disables that.
+	 */
+	if (dev_is_pci(dev))
+		return pci_acs_path_enabled(to_pci_dev(dev), NULL,
+					    REQ_ACS_FLAGS);
+
+	/*
+	 * Otherwise, the device came from DT/ACPI, assume it is static and
+	 * then singleton can know from the device count in the group.
+	 */
+	return true;
+}
+
+/*
+ * iommu_attach_device_pasid() - Attach a domain to pasid of device
+ * @domain: the iommu domain.
+ * @dev: the attached device.
+ * @pasid: the pasid of the device.
+ *
+ * Return: 0 on success, or an error.
+ */
+int iommu_attach_device_pasid(struct iommu_domain *domain,
+			      struct device *dev, ioasid_t pasid)
+{
+	struct iommu_group *group;
+	int ret = -ENODEV;
+	void *curr;
+
+	if (!domain->ops->set_dev_pasid)
+		return -EOPNOTSUPP;
+
+	group = iommu_group_get(dev);
+	if (!group)
+		return -ENODEV;
+
+	mutex_lock(&group->mutex);
+	if (!iommu_group_device_pasid_viable(group, dev))
+		goto out_unlock;
+	curr = xa_cmpxchg(&group->pasid_array, pasid, NULL, domain, GFP_KERNEL);
+	if (curr) {
+		ret = xa_err(curr) ? : -EBUSY;
+		goto out_unlock;
+	}
+	ret = domain->ops->set_dev_pasid(domain, dev, pasid);
+	if (ret)
+		xa_erase(&group->pasid_array, pasid);
+out_unlock:
+	mutex_unlock(&group->mutex);
+	iommu_group_put(group);
+
+	return ret;
+}
+
+/*
+ * iommu_detach_device_pasid() - Detach the domain from pasid of device
+ * @domain: the iommu domain.
+ * @dev: the attached device.
+ * @pasid: the pasid of the device.
+ *
+ * The @domain must have been attached to @pasid of the @dev with
+ * iommu_detach_device_pasid().
+ */
+void iommu_detach_device_pasid(struct iommu_domain *domain, struct 
device *dev,
+			       ioasid_t pasid)
+{
+	struct iommu_group *group = iommu_group_get(dev);
+
+	mutex_lock(&group->mutex);
+	domain->ops->set_dev_pasid(group->blocking_domain, dev, pasid);
+	WARN_ON(xa_erase(&group->pasid_array, pasid) != domain);
+	mutex_unlock(&group->mutex);
+
+	iommu_group_put(group);
+}
+
+/*
+ * iommu_get_domain_for_dev_pasid() - Retrieve domain for @pasid of @dev
+ * @dev: the queried device
+ * @pasid: the pasid of the device
+ *
+ * This is a variant of iommu_get_domain_for_dev(). It returns the existing
+ * domain attached to pasid of a device. It's only for internal use of the
+ * IOMMU subsystem. The caller must take care to avoid any possible
+ * use-after-free case.
+ *
+ * Return: attached domain on success, NULL otherwise.
+ */
+struct iommu_domain *
+iommu_get_domain_for_dev_pasid(struct device *dev, ioasid_t pasid)
+{
+	struct iommu_domain *domain;
+	struct iommu_group *group;
+
+	if (!pasid_valid(pasid))
+		return NULL;
+
+	group = iommu_group_get(dev);
+	if (!group)
+		return NULL;
+	/*
+	 * The xarray protects its internal state with RCU. Hence the domain
+	 * obtained is either NULL or fully formed.
+	 */
+	domain = xa_load(&group->pasid_array, pasid);
+	iommu_group_put(group);
+
+	return domain;
+}

Best regards,
baolu

  reply	other threads:[~2022-07-29  2:49 UTC|newest]

Thread overview: 90+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-05  5:06 [PATCH v10 00/12] iommu: SVA and IOPF refactoring Lu Baolu
2022-07-05  5:06 ` [PATCH v10 01/12] iommu: Add max_pasids field in struct iommu_device Lu Baolu
2022-07-23 13:57   ` Jason Gunthorpe
2022-07-31 11:54   ` Yi Liu
2022-07-31 13:33     ` Baolu Lu
2022-07-05  5:07 ` [PATCH v10 02/12] iommu: Add max_pasids field in struct dev_iommu Lu Baolu
2022-07-23 14:02   ` Jason Gunthorpe
2022-07-31 11:55   ` Yi Liu
2022-07-05  5:07 ` [PATCH v10 03/12] iommu: Remove SVM_FLAG_SUPERVISOR_MODE support Lu Baolu
2022-07-31 12:01   ` Yi Liu
2022-07-31 13:39     ` Baolu Lu
2022-07-05  5:07 ` [PATCH v10 04/12] iommu: Add attach/detach_dev_pasid iommu interface Lu Baolu
2022-07-07  1:51   ` Tian, Kevin
2022-07-23 14:11   ` Jason Gunthorpe
2022-07-24  7:03     ` Baolu Lu
2022-07-25 14:40       ` Jason Gunthorpe
2022-07-26  6:23         ` Baolu Lu
2022-07-26 13:57           ` Jason Gunthorpe
2022-07-27  3:20             ` Tian, Kevin
2022-07-27 11:53               ` Jason Gunthorpe
2022-07-28  3:06                 ` Tian, Kevin
2022-07-28 11:59                   ` Jason Gunthorpe
2022-07-29  2:49                     ` Baolu Lu [this message]
2022-07-29  2:56                       ` Tian, Kevin
2022-07-29  3:20                         ` Baolu Lu
2022-07-29  4:22                           ` Tian, Kevin
2022-07-30  6:17                             ` Baolu Lu
2022-07-29  2:51                     ` Tian, Kevin
2022-07-29 12:22                       ` Jason Gunthorpe
2022-07-30  6:23                         ` Baolu Lu
2022-07-28  2:44             ` Baolu Lu
2022-07-28  6:27               ` Baolu Lu
2022-08-02  2:19             ` Baolu Lu
2022-08-02 12:37               ` Jason Gunthorpe
2022-08-03 13:07                 ` Baolu Lu
2022-08-03 19:03                   ` Jason Gunthorpe
2022-08-04  2:03                     ` Tian, Kevin
2022-08-04  2:42                     ` Baolu Lu
2022-07-24  7:23     ` Baolu Lu
2022-07-24  8:39     ` Baolu Lu
2022-07-24  9:13     ` Baolu Lu
2022-07-25  7:46       ` Tian, Kevin
2022-07-25 10:11         ` Baolu Lu
2022-07-31 12:10   ` Yi Liu
2022-07-05  5:07 ` [PATCH v10 05/12] iommu: Add IOMMU SVA domain support Lu Baolu
2022-07-07  1:52   ` Tian, Kevin
2022-07-07  3:01     ` Baolu Lu
2022-07-23 14:15   ` Jason Gunthorpe
2022-07-31 12:19   ` Yi Liu
2022-07-05  5:07 ` [PATCH v10 06/12] iommu/vt-d: Add " Lu Baolu
2022-07-23 14:16   ` Jason Gunthorpe
2022-07-31 12:20   ` Yi Liu
2022-07-05  5:07 ` [PATCH v10 07/12] arm-smmu-v3/sva: " Lu Baolu
2022-07-23 14:20   ` Jason Gunthorpe
2022-07-24 11:58     ` Baolu Lu
2022-07-05  5:07 ` [PATCH v10 08/12] iommu/sva: Refactoring iommu_sva_bind/unbind_device() Lu Baolu
2022-07-05 17:43   ` Jean-Philippe Brucker
2022-07-07  1:56   ` Tian, Kevin
2022-07-07  3:02     ` Baolu Lu
2022-07-23 14:26   ` Jason Gunthorpe
2022-07-24 13:48     ` Baolu Lu
2022-07-25  7:39       ` Jean-Philippe Brucker
2022-07-25  8:02         ` Tian, Kevin
2022-07-25  8:47           ` Jean-Philippe Brucker
2022-07-25  9:33         ` Baolu Lu
2022-07-25  9:52           ` Jean-Philippe Brucker
2022-07-25 14:46             ` Jason Gunthorpe
2022-07-25  7:50       ` Tian, Kevin
2022-07-25 10:22         ` Baolu Lu
2022-07-25 14:47           ` Jason Gunthorpe
2022-07-26  8:47             ` Baolu Lu
2022-07-31 12:36   ` Yi Liu
2022-07-31 13:45     ` Baolu Lu
2022-07-31 12:55   ` Yi Liu
2022-07-31 13:51     ` Baolu Lu
2022-07-05  5:07 ` [PATCH v10 09/12] iommu: Remove SVA related callbacks from iommu ops Lu Baolu
2022-07-23 14:27   ` Jason Gunthorpe
2022-07-31 12:38   ` Yi Liu
2022-07-05  5:07 ` [PATCH v10 10/12] iommu: Prepare IOMMU domain for IOPF Lu Baolu
2022-07-07  1:58   ` Tian, Kevin
2022-07-23 14:33   ` Jason Gunthorpe
2022-07-24 14:04     ` Baolu Lu
2022-07-25 14:49       ` Jason Gunthorpe
2022-07-31 12:50   ` Yi Liu
2022-07-31 13:47     ` Baolu Lu
2022-07-05  5:07 ` [PATCH v10 11/12] iommu: Per-domain I/O page fault handling Lu Baolu
2022-07-07  2:06   ` Tian, Kevin
2022-07-23 14:34   ` Jason Gunthorpe
2022-07-05  5:07 ` [PATCH v10 12/12] iommu: Rename iommu-sva-lib.{c,h} Lu Baolu
2022-07-23 14:34   ` Jason Gunthorpe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=78376ca4-9b55-7609-abf1-27a1a376a8e0@linux.intel.com \
    --to=baolu.lu@linux.intel.com \
    --cc=ashok.raj@intel.com \
    --cc=dave.jiang@intel.com \
    --cc=eric.auger@redhat.com \
    --cc=hch@infradead.org \
    --cc=iommu@lists.linux.dev \
    --cc=jacob.jun.pan@intel.com \
    --cc=jean-philippe@linaro.com \
    --cc=jean-philippe@linaro.org \
    --cc=jgg@nvidia.com \
    --cc=joro@8bytes.org \
    --cc=kevin.tian@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=tony.zhu@intel.com \
    --cc=vkoul@kernel.org \
    --cc=will@kernel.org \
    --cc=yi.l.liu@intel.com \
    --cc=zhangfei.gao@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.