public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Lu Baolu <baolu.lu@linux.intel.com>
To: Joerg Roedel <joro@8bytes.org>, Jason Gunthorpe <jgg@nvidia.com>,
	Christoph Hellwig <hch@infradead.org>,
	Kevin Tian <kevin.tian@intel.com>,
	Ashok Raj <ashok.raj@intel.com>, Will Deacon <will@kernel.org>,
	Robin Murphy <robin.murphy@arm.com>,
	Jean-Philippe Brucker <jean-philippe@linaro.com>
Cc: Eric Auger <eric.auger@redhat.com>, Liu Yi L <yi.l.liu@intel.com>,
	Jacob jun Pan <jacob.jun.pan@intel.com>,
	iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org,
	Lu Baolu <baolu.lu@linux.intel.com>
Subject: [PATCH RFC v3 02/12] iommu: Add a flag to indicate immutable singleton group
Date: Sun, 10 Apr 2022 18:24:33 +0800	[thread overview]
Message-ID: <20220410102443.294128-3-baolu.lu@linux.intel.com> (raw)
In-Reply-To: <20220410102443.294128-1-baolu.lu@linux.intel.com>

Some features require that a single device must be immutably isolated,
even when hot plug is supported. For example, the SVA bind()/unbind()
interfaces require that the device exists in a singleton group. If we
have a singleton group that doesn't have ACS (or similar technologies)
and someone hotplugs in another device on a bridge, then our SVA is
completely broken and we get data corruption.

This adds a flag in the iommu_group struct to indicate an immutable
singleton group, and uses standard PCI bus topology, isolation features,
and DMA alias quirks to set the flag. If the device came from DT, assume
it is static and then the singleton attribute can know from the device
count in the group.

Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Suggested-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
 drivers/iommu/iommu.c | 67 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 57 insertions(+), 10 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 0c42ece25854..56ffbf5fdc18 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -48,6 +48,7 @@ struct iommu_group {
 	struct list_head entry;
 	unsigned int owner_cnt;
 	void *owner;
+	bool immutable_singleton;
 };
 
 struct group_device {
@@ -74,6 +75,16 @@ static const char * const iommu_group_resv_type_string[] = {
 #define IOMMU_CMD_LINE_DMA_API		BIT(0)
 #define IOMMU_CMD_LINE_STRICT		BIT(1)
 
+/*
+ * To consider a PCI device isolated, we require ACS to support Source
+ * Validation, Request Redirection, Completer Redirection, and Upstream
+ * Forwarding.  This effectively means that devices cannot spoof their
+ * requester ID, requests and completions cannot be redirected, and all
+ * transactions are forwarded upstream, even as it passes through a
+ * bridge where the target device is downstream.
+ */
+#define REQ_ACS_FLAGS   (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
+
 static int iommu_alloc_default_domain(struct iommu_group *group,
 				      struct device *dev);
 static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
@@ -89,6 +100,7 @@ static int iommu_create_device_direct_mappings(struct iommu_group *group,
 static struct iommu_group *iommu_group_get_for_dev(struct device *dev);
 static ssize_t iommu_group_store_type(struct iommu_group *group,
 				      const char *buf, size_t count);
+static int iommu_group_device_count(struct iommu_group *group);
 
 #define IOMMU_GROUP_ATTR(_name, _mode, _show, _store)		\
 struct iommu_group_attribute iommu_group_attr_##_name =		\
@@ -844,6 +856,37 @@ static bool iommu_is_attach_deferred(struct device *dev)
 	return false;
 }
 
+static int has_pci_alias(struct pci_dev *pdev, u16 alias, void *opaque)
+{
+	return -EEXIST;
+}
+
+static bool pci_immutably_isolated(struct pci_dev *pdev)
+{
+	/* Skip the bridges. */
+	if (pci_is_bridge(pdev))
+		return false;
+
+	/*
+	 * The device could be considered to be fully isolated if
+	 * all devices on the path from the parent to the host-PCI
+	 * bridge are protected from peer-to-peer DMA by ACS.
+	 */
+	if (!pci_is_root_bus(pdev->bus) &&
+	    !pci_acs_path_enabled(pdev->bus->self, NULL, REQ_ACS_FLAGS))
+		return false;
+
+	/* Multi-function devices should have ACS enabled. */
+	if (pdev->multifunction && !pci_acs_enabled(pdev, REQ_ACS_FLAGS))
+		return false;
+
+	/* Filter out devices which has any alias device. */
+	if (pci_for_each_dma_alias(pdev, has_pci_alias, NULL))
+		return false;
+
+	return true;
+}
+
 /**
  * iommu_group_add_device - add a device to an iommu group
  * @group: the group into which to add the device (reference should be held)
@@ -898,6 +941,20 @@ int iommu_group_add_device(struct iommu_group *group, struct device *dev)
 	list_add_tail(&device->list, &group->devices);
 	if (group->domain  && !iommu_is_attach_deferred(dev))
 		ret = __iommu_attach_device(group->domain, dev);
+
+	/*
+	 * Use standard PCI bus topology, isolation features, and DMA
+	 * alias quirks to set the immutable singleton attribute. If
+	 * the device came from DT, assume it is static and then
+	 * singleton can know from the device count in the group.
+	 */
+	if (dev_is_pci(dev))
+		group->immutable_singleton =
+				pci_immutably_isolated(to_pci_dev(dev));
+	else if (is_of_node(dev_fwnode(dev)))
+		group->immutable_singleton =
+				(iommu_group_device_count(group) == 1);
+
 	mutex_unlock(&group->mutex);
 	if (ret)
 		goto err_put_group;
@@ -1290,16 +1347,6 @@ EXPORT_SYMBOL_GPL(iommu_group_id);
 static struct iommu_group *get_pci_alias_group(struct pci_dev *pdev,
 					       unsigned long *devfns);
 
-/*
- * To consider a PCI device isolated, we require ACS to support Source
- * Validation, Request Redirection, Completer Redirection, and Upstream
- * Forwarding.  This effectively means that devices cannot spoof their
- * requester ID, requests and completions cannot be redirected, and all
- * transactions are forwarded upstream, even as it passes through a
- * bridge where the target device is downstream.
- */
-#define REQ_ACS_FLAGS   (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
-
 /*
  * For multifunction devices which are not isolated from each other, find
  * all the other non-isolated functions and look for existing groups.  For
-- 
2.25.1


  parent reply	other threads:[~2022-04-10 10:27 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-10 10:24 [PATCH RFC v3 00/12] iommu: SVA and IOPF refactoring Lu Baolu
2022-04-10 10:24 ` [PATCH RFC v3 01/12] iommu: Add pasid_bits field in struct dev_iommu Lu Baolu
2022-04-10 10:24 ` Lu Baolu [this message]
2022-04-12  3:15   ` [PATCH RFC v3 02/12] iommu: Add a flag to indicate immutable singleton group Tian, Kevin
2022-04-12  5:08     ` Lu Baolu
2022-04-12  6:34       ` Yi Liu
2022-04-12 11:56         ` Lu Baolu
2022-04-12  7:37       ` Tian, Kevin
2022-04-12 13:02         ` Lu Baolu
2022-04-12 23:32           ` Tian, Kevin
2022-04-13 12:02             ` Lu Baolu
2022-04-12  7:39   ` Tian, Kevin
2022-04-12 13:10     ` Lu Baolu
2022-04-10 10:24 ` [PATCH RFC v3 03/12] iommu: Add attach/detach_dev_pasid domain ops Lu Baolu
2022-04-10 10:24 ` [PATCH RFC v3 04/12] iommu/sva: Basic data structures for SVA Lu Baolu
2022-04-12  6:49   ` Tian, Kevin
2022-04-12 11:58     ` Lu Baolu
2022-04-12  6:56   ` Tian, Kevin
2022-04-12 12:08     ` Lu Baolu
2022-04-10 10:24 ` [PATCH RFC v3 05/12] iommu/vt-d: Remove SVM_FLAG_SUPERVISOR_MODE support Lu Baolu
2022-04-10 10:24 ` [PATCH RFC v3 06/12] iommu/vt-d: Add SVA domain support Lu Baolu
2022-04-10 10:24 ` [PATCH RFC v3 07/12] arm-smmu-v3/sva: " Lu Baolu
2022-04-10 10:24 ` [PATCH RFC v3 08/12] iommu/sva: Use attach/detach_pasid_dev in SVA interfaces Lu Baolu
2022-04-12  7:19   ` Tian, Kevin
2022-04-12 12:53     ` Lu Baolu
2022-04-12 23:36       ` Tian, Kevin
2022-04-13 11:57         ` Lu Baolu
2022-04-14  3:44           ` Tian, Kevin
2022-04-10 10:24 ` [PATCH RFC v3 09/12] iommu: Remove SVA related callbacks from iommu ops Lu Baolu
2022-04-10 10:24 ` [PATCH RFC v3 10/12] iommu: Prepare IOMMU domain for IOPF Lu Baolu
2022-04-10 10:24 ` [PATCH RFC v3 11/12] iommu: Per-domain I/O page fault handling Lu Baolu
2022-04-10 10:24 ` [PATCH RFC v3 12/12] iommu: Rename iommu-sva-lib.{c,h} Lu Baolu

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=20220410102443.294128-3-baolu.lu@linux.intel.com \
    --to=baolu.lu@linux.intel.com \
    --cc=ashok.raj@intel.com \
    --cc=eric.auger@redhat.com \
    --cc=hch@infradead.org \
    --cc=iommu@lists.linux-foundation.org \
    --cc=jacob.jun.pan@intel.com \
    --cc=jean-philippe@linaro.com \
    --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=will@kernel.org \
    --cc=yi.l.liu@intel.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox