linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v9 0/4] iommu: Add support to change default domain of
@ 2020-11-21 13:56 Lu Baolu
  2020-11-21 13:56 ` [PATCH v9 1/4] iommu: Move def_domain type check for untrusted device into core Lu Baolu
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Lu Baolu @ 2020-11-21 13:56 UTC (permalink / raw)
  To: Will Deacon, Joerg Roedel
  Cc: Ashok Raj, Christoph Hellwig, Sohil Mehta, Robin Murphy,
	Jacob Pan, iommu, linux-kernel, Lu Baolu

Hi,

The description and last post of this series could be found here.

https://lore.kernel.org/linux-iommu/20200925190620.18732-1-ashok.raj@intel.com/

Change log in this series:
 1. Changes according to comments at
    https://lore.kernel.org/linux-iommu/243ce89c33fe4b9da4c56ba35acebf81@huawei.com/
    - Move the untrusted device check to iommu core
    - Remove the requirement of def_domain_type callback
 
2. Changes according to comments at
    https://lore.kernel.org/linux-iommu/20201118135153.GB2177@willie-the-truck/
    - Replace pr_err_ratelimited() with dev_err_ratelimited() for more
      context.
    - Refine the getting default domain type code.
    - Add comments about the lock mechanism (vs. device release path)
      for future reference.

    https://lore.kernel.org/linux-iommu/20201118135137.GA2177@willie-the-truck/
    - Refine the ABI document.

Best regards,
baolu

Lu Baolu (1):
  iommu: Move def_domain type check for untrusted device into core

Sai Praneeth Prakhya (3):
  iommu: Add support to change default domain of an iommu group
  iommu: Take lock before reading iommu group default domain type
  iommu: Document usage of "/sys/kernel/iommu_groups/<grp_id>/type" file

 .../ABI/testing/sysfs-kernel-iommu_groups     |  29 ++
 drivers/iommu/intel/iommu.c                   |   7 -
 drivers/iommu/iommu.c                         | 255 +++++++++++++++++-
 3 files changed, 276 insertions(+), 15 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v9 1/4] iommu: Move def_domain type check for untrusted device into core
  2020-11-21 13:56 [PATCH v9 0/4] iommu: Add support to change default domain of Lu Baolu
@ 2020-11-21 13:56 ` Lu Baolu
  2020-11-23 12:04   ` Will Deacon
  2020-11-21 13:56 ` [PATCH v9 2/4] iommu: Add support to change default domain of an iommu group Lu Baolu
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Lu Baolu @ 2020-11-21 13:56 UTC (permalink / raw)
  To: Will Deacon, Joerg Roedel
  Cc: Ashok Raj, Christoph Hellwig, Sohil Mehta, Robin Murphy,
	Jacob Pan, iommu, linux-kernel, Lu Baolu,
	Shameerali Kolothum Thodi

So that the vendor iommu drivers are no more required to provide the
def_domain_type callback to always isolate the untrusted devices.

Link: https://lore.kernel.org/linux-iommu/243ce89c33fe4b9da4c56ba35acebf81@huawei.com/
Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
 drivers/iommu/intel/iommu.c |  7 -------
 drivers/iommu/iommu.c       | 21 ++++++++++++++-------
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index af3abd285214..6711f78141a4 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -2916,13 +2916,6 @@ static int device_def_domain_type(struct device *dev)
 	if (dev_is_pci(dev)) {
 		struct pci_dev *pdev = to_pci_dev(dev);
 
-		/*
-		 * Prevent any device marked as untrusted from getting
-		 * placed into the statically identity mapping domain.
-		 */
-		if (pdev->untrusted)
-			return IOMMU_DOMAIN_DMA;
-
 		if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
 			return IOMMU_DOMAIN_IDENTITY;
 
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 88b0c9192d8c..3256784c0358 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1457,13 +1457,23 @@ struct iommu_group *fsl_mc_device_group(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(fsl_mc_device_group);
 
-static int iommu_get_def_domain_type(struct device *dev)
+/* Get the mandatary def_domain type for device. Otherwise, return 0. */
+static int iommu_get_mandatory_def_domain_type(struct device *dev)
 {
 	const struct iommu_ops *ops = dev->bus->iommu_ops;
-	unsigned int type = 0;
+
+	if (dev_is_pci(dev) && to_pci_dev(dev)->untrusted)
+		return IOMMU_DOMAIN_DMA;
 
 	if (ops->def_domain_type)
-		type = ops->def_domain_type(dev);
+		return ops->def_domain_type(dev);
+
+	return 0;
+}
+
+static int iommu_get_def_domain_type(struct device *dev)
+{
+	int type = iommu_get_mandatory_def_domain_type(dev);
 
 	return (type == 0) ? iommu_def_domain_type : type;
 }
@@ -1645,13 +1655,10 @@ struct __group_domain_type {
 
 static int probe_get_default_domain_type(struct device *dev, void *data)
 {
-	const struct iommu_ops *ops = dev->bus->iommu_ops;
 	struct __group_domain_type *gtype = data;
 	unsigned int type = 0;
 
-	if (ops->def_domain_type)
-		type = ops->def_domain_type(dev);
-
+	type = iommu_get_mandatory_def_domain_type(dev);
 	if (type) {
 		if (gtype->type && gtype->type != type) {
 			dev_warn(dev, "Device needs domain type %s, but device %s in the same iommu group requires type %s - using default\n",
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v9 2/4] iommu: Add support to change default domain of an iommu group
  2020-11-21 13:56 [PATCH v9 0/4] iommu: Add support to change default domain of Lu Baolu
  2020-11-21 13:56 ` [PATCH v9 1/4] iommu: Move def_domain type check for untrusted device into core Lu Baolu
@ 2020-11-21 13:56 ` Lu Baolu
  2020-11-21 13:56 ` [PATCH v9 3/4] iommu: Take lock before reading iommu group default domain type Lu Baolu
  2020-11-21 13:56 ` [PATCH v9 4/4] iommu: Document usage of "/sys/kernel/iommu_groups/<grp_id>/type" file Lu Baolu
  3 siblings, 0 replies; 10+ messages in thread
From: Lu Baolu @ 2020-11-21 13:56 UTC (permalink / raw)
  To: Will Deacon, Joerg Roedel
  Cc: Ashok Raj, Christoph Hellwig, Sohil Mehta, Robin Murphy,
	Jacob Pan, iommu, linux-kernel, Sai Praneeth Prakhya,
	Will Deacon, Lu Baolu

From: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>

Presently, the default domain of an iommu group is allocated during boot
time and it cannot be changed later. So, the device would typically be
either in identity (also known as pass_through) mode or the device would be
in DMA mode as long as the machine is up and running. There is no way to
change the default domain type dynamically i.e. after booting, a device
cannot switch between identity mode and DMA mode.

But, assume a use case wherein the user trusts the device and believes that
the OS is secure enough and hence wants *only* this device to bypass IOMMU
(so that it could be high performing) whereas all the other devices to go
through IOMMU (so that the system is protected). Presently, this use case
is not supported. It will be helpful if there is some way to change the
default domain of an iommu group dynamically. Hence, add such support.

A privileged user could request the kernel to change the default domain
type of a iommu group by writing to
"/sys/kernel/iommu_groups/<grp_id>/type" file. Presently, only three values
are supported
1. identity: all the DMA transactions from the device in this group are
             *not* translated by the iommu
2. DMA: all the DMA transactions from the device in this group are
        translated by the iommu
3. auto: change to the type the device was booted with

Note:
1. Default domain of an iommu group with two or more devices cannot be
   changed.
2. The device in the iommu group shouldn't be bound to any driver.
3. The device shouldn't be assigned to user for direct access.
4. The change request will fail if any device in the group has a mandatory
   default domain type and the requested one conflicts with that.

Please see "Documentation/ABI/testing/sysfs-kernel-iommu_groups" for more
information.

Cc: Christoph Hellwig <hch@lst.de>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Sohil Mehta <sohil.mehta@intel.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Signed-off-by: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
 drivers/iommu/iommu.c | 232 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 231 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 3256784c0358..716bd602b0ed 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -93,6 +93,8 @@ static void __iommu_detach_group(struct iommu_domain *domain,
 static int iommu_create_device_direct_mappings(struct iommu_group *group,
 					       struct device *dev);
 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);
 
 #define IOMMU_GROUP_ATTR(_name, _mode, _show, _store)		\
 struct iommu_group_attribute iommu_group_attr_##_name =		\
@@ -525,7 +527,8 @@ static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL);
 static IOMMU_GROUP_ATTR(reserved_regions, 0444,
 			iommu_group_show_resv_regions, NULL);
 
-static IOMMU_GROUP_ATTR(type, 0444, iommu_group_show_type, NULL);
+static IOMMU_GROUP_ATTR(type, 0644, iommu_group_show_type,
+			iommu_group_store_type);
 
 static void iommu_group_release(struct kobject *kobj)
 {
@@ -3034,3 +3037,230 @@ u32 iommu_sva_get_pasid(struct iommu_sva *handle)
 	return ops->sva_get_pasid(handle);
 }
 EXPORT_SYMBOL_GPL(iommu_sva_get_pasid);
+
+/*
+ * Changes the default domain of an iommu group that has *only* one device
+ *
+ * @group: The group for which the default domain should be changed
+ * @prev_dev: The device in the group (this is used to make sure that the device
+ *	 hasn't changed after the caller has called this function)
+ * @type: The type of the new default domain that gets associated with the group
+ *
+ * Returns 0 on success and error code on failure
+ *
+ * Note:
+ * 1. Presently, this function is called only when user requests to change the
+ *    group's default domain type through /sys/kernel/iommu_groups/<grp_id>/type
+ *    Please take a closer look if intended to use for other purposes.
+ */
+static int iommu_change_dev_def_domain(struct iommu_group *group,
+				       struct device *prev_dev, int type)
+{
+	struct iommu_domain *prev_dom;
+	struct group_device *grp_dev;
+	int ret, dev_def_dom;
+	struct device *dev;
+
+	if (!group)
+		return -EINVAL;
+
+	mutex_lock(&group->mutex);
+
+	if (group->default_domain != group->domain) {
+		dev_err_ratelimited(prev_dev, "Group not assigned to default domain\n");
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/*
+	 * iommu group wasn't locked while acquiring device lock in
+	 * iommu_group_store_type(). So, make sure that the device count hasn't
+	 * changed while acquiring device lock.
+	 *
+	 * Changing default domain of an iommu group with two or more devices
+	 * isn't supported because there could be a potential deadlock. Consider
+	 * the following scenario. T1 is trying to acquire device locks of all
+	 * the devices in the group and before it could acquire all of them,
+	 * there could be another thread T2 (from different sub-system and use
+	 * case) that has already acquired some of the device locks and might be
+	 * waiting for T1 to release other device locks.
+	 */
+	if (iommu_group_device_count(group) != 1) {
+		dev_err_ratelimited(prev_dev, "Cannot change default domain: Group has more than one device\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Since group has only one device */
+	grp_dev = list_first_entry(&group->devices, struct group_device, list);
+	dev = grp_dev->dev;
+
+	if (prev_dev != dev) {
+		dev_err_ratelimited(prev_dev, "Cannot change default domain: Device has been changed\n");
+		ret = -EBUSY;
+		goto out;
+	}
+
+	prev_dom = group->default_domain;
+	if (!prev_dom) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	dev_def_dom = iommu_get_mandatory_def_domain_type(dev);
+
+	/* Check if user requested domain is supported by the device or not */
+	if (!type) {
+		/*
+		 * If the user hasn't requested any specific type of domain and
+		 * if the device supports both the domains, then default to the
+		 * domain the device was booted with
+		 */
+		type = iommu_get_def_domain_type(dev);
+	} else if (dev_def_dom && type != dev_def_dom) {
+		dev_err_ratelimited(prev_dev, "Device cannot be in %s domain\n",
+				    iommu_domain_type_str(type));
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Switch to a new domain only if the requested domain type is different
+	 * from the existing default domain type
+	 */
+	if (prev_dom->type == type) {
+		ret = 0;
+		goto out;
+	}
+
+	/* Sets group->default_domain to the newly allocated domain */
+	ret = iommu_group_alloc_default_domain(dev->bus, group, type);
+	if (ret)
+		goto out;
+
+	ret = iommu_create_device_direct_mappings(group, dev);
+	if (ret)
+		goto free_new_domain;
+
+	ret = __iommu_attach_device(group->default_domain, dev);
+	if (ret)
+		goto free_new_domain;
+
+	group->domain = group->default_domain;
+
+	/*
+	 * Release the mutex here because ops->probe_finalize() call-back of
+	 * some vendor IOMMU drivers calls arm_iommu_attach_device() which
+	 * in-turn might call back into IOMMU core code, where it tries to take
+	 * group->mutex, resulting in a deadlock.
+	 */
+	mutex_unlock(&group->mutex);
+
+	/* Make sure dma_ops is appropriatley set */
+	iommu_group_do_probe_finalize(dev, group->default_domain);
+	iommu_domain_free(prev_dom);
+	return 0;
+
+free_new_domain:
+	iommu_domain_free(group->default_domain);
+	group->default_domain = prev_dom;
+	group->domain = prev_dom;
+
+out:
+	mutex_unlock(&group->mutex);
+
+	return ret;
+}
+
+/*
+ * Changing the default domain through sysfs requires the users to ubind the
+ * drivers from the devices in the iommu group. Return failure if this doesn't
+ * meet.
+ *
+ * We need to consider the race between this and the device release path.
+ * device_lock(dev) is used here to guarantee that the device release path
+ * will not be entered at the same time.
+ */
+static ssize_t iommu_group_store_type(struct iommu_group *group,
+				      const char *buf, size_t count)
+{
+	struct group_device *grp_dev;
+	struct device *dev;
+	int ret, req_type;
+
+	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+		return -EACCES;
+
+	if (WARN_ON(!group))
+		return -EINVAL;
+
+	if (sysfs_streq(buf, "identity"))
+		req_type = IOMMU_DOMAIN_IDENTITY;
+	else if (sysfs_streq(buf, "DMA"))
+		req_type = IOMMU_DOMAIN_DMA;
+	else if (sysfs_streq(buf, "auto"))
+		req_type = 0;
+	else
+		return -EINVAL;
+
+	/*
+	 * Lock/Unlock the group mutex here before device lock to
+	 * 1. Make sure that the iommu group has only one device (this is a
+	 *    prerequisite for step 2)
+	 * 2. Get struct *dev which is needed to lock device
+	 */
+	mutex_lock(&group->mutex);
+	if (iommu_group_device_count(group) != 1) {
+		mutex_unlock(&group->mutex);
+		pr_err_ratelimited("Cannot change default domain: Group has more than one device\n");
+		return -EINVAL;
+	}
+
+	/* Since group has only one device */
+	grp_dev = list_first_entry(&group->devices, struct group_device, list);
+	dev = grp_dev->dev;
+	get_device(dev);
+
+	/*
+	 * Don't hold the group mutex because taking group mutex first and then
+	 * the device lock could potentially cause a deadlock as below. Assume
+	 * two threads T1 and T2. T1 is trying to change default domain of an
+	 * iommu group and T2 is trying to hot unplug a device or release [1] VF
+	 * of a PCIe device which is in the same iommu group. T1 takes group
+	 * mutex and before it could take device lock assume T2 has taken device
+	 * lock and is yet to take group mutex. Now, both the threads will be
+	 * waiting for the other thread to release lock. Below, lock order was
+	 * suggested.
+	 * device_lock(dev);
+	 *	mutex_lock(&group->mutex);
+	 *		iommu_change_dev_def_domain();
+	 *	mutex_unlock(&group->mutex);
+	 * device_unlock(dev);
+	 *
+	 * [1] Typical device release path
+	 * device_lock() from device/driver core code
+	 *  -> bus_notifier()
+	 *   -> iommu_bus_notifier()
+	 *    -> iommu_release_device()
+	 *     -> ops->release_device() vendor driver calls back iommu core code
+	 *      -> mutex_lock() from iommu core code
+	 */
+	mutex_unlock(&group->mutex);
+
+	/* Check if the device in the group still has a driver bound to it */
+	device_lock(dev);
+	if (device_is_bound(dev)) {
+		pr_err_ratelimited("Device is still bound to driver\n");
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ret = iommu_change_dev_def_domain(group, dev, req_type);
+	ret = ret ?: count;
+
+out:
+	device_unlock(dev);
+	put_device(dev);
+
+	return ret;
+}
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v9 3/4] iommu: Take lock before reading iommu group default domain type
  2020-11-21 13:56 [PATCH v9 0/4] iommu: Add support to change default domain of Lu Baolu
  2020-11-21 13:56 ` [PATCH v9 1/4] iommu: Move def_domain type check for untrusted device into core Lu Baolu
  2020-11-21 13:56 ` [PATCH v9 2/4] iommu: Add support to change default domain of an iommu group Lu Baolu
@ 2020-11-21 13:56 ` Lu Baolu
  2020-11-21 13:56 ` [PATCH v9 4/4] iommu: Document usage of "/sys/kernel/iommu_groups/<grp_id>/type" file Lu Baolu
  3 siblings, 0 replies; 10+ messages in thread
From: Lu Baolu @ 2020-11-21 13:56 UTC (permalink / raw)
  To: Will Deacon, Joerg Roedel
  Cc: Ashok Raj, Christoph Hellwig, Sohil Mehta, Robin Murphy,
	Jacob Pan, iommu, linux-kernel, Sai Praneeth Prakhya,
	Will Deacon, Lu Baolu

From: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>

"/sys/kernel/iommu_groups/<grp_id>/type" file could be read to find out the
default domain type of an iommu group. The default domain of an iommu group
doesn't change after booting and hence could be read directly. But,
after addding support to dynamically change iommu group default domain, the
above assumption no longer stays valid.

iommu group default domain type could be changed at any time by writing to
"/sys/kernel/iommu_groups/<grp_id>/type". So, take group mutex before
reading iommu group default domain type so that the user wouldn't see stale
values or iommu_group_show_type() doesn't try to derefernce stale pointers.

Cc: Christoph Hellwig <hch@lst.de>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Sohil Mehta <sohil.mehta@intel.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Signed-off-by: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
 drivers/iommu/iommu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 716bd602b0ed..aad465c38067 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -501,6 +501,7 @@ static ssize_t iommu_group_show_type(struct iommu_group *group,
 {
 	char *type = "unknown\n";
 
+	mutex_lock(&group->mutex);
 	if (group->default_domain) {
 		switch (group->default_domain->type) {
 		case IOMMU_DOMAIN_BLOCKED:
@@ -517,6 +518,7 @@ static ssize_t iommu_group_show_type(struct iommu_group *group,
 			break;
 		}
 	}
+	mutex_unlock(&group->mutex);
 	strcpy(buf, type);
 
 	return strlen(type);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v9 4/4] iommu: Document usage of "/sys/kernel/iommu_groups/<grp_id>/type" file
  2020-11-21 13:56 [PATCH v9 0/4] iommu: Add support to change default domain of Lu Baolu
                   ` (2 preceding siblings ...)
  2020-11-21 13:56 ` [PATCH v9 3/4] iommu: Take lock before reading iommu group default domain type Lu Baolu
@ 2020-11-21 13:56 ` Lu Baolu
  3 siblings, 0 replies; 10+ messages in thread
From: Lu Baolu @ 2020-11-21 13:56 UTC (permalink / raw)
  To: Will Deacon, Joerg Roedel
  Cc: Ashok Raj, Christoph Hellwig, Sohil Mehta, Robin Murphy,
	Jacob Pan, iommu, linux-kernel, Sai Praneeth Prakhya,
	Will Deacon, Lu Baolu

From: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>

The default domain type of an iommu group can be changed by writing to
"/sys/kernel/iommu_groups/<grp_id>/type" file. Hence, document it's usage
and more importantly spell out its limitations.

Cc: Christoph Hellwig <hch@lst.de>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Sohil Mehta <sohil.mehta@intel.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Signed-off-by: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
 .../ABI/testing/sysfs-kernel-iommu_groups     | 29 +++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-kernel-iommu_groups b/Documentation/ABI/testing/sysfs-kernel-iommu_groups
index 017f5bc3920c..407b1628d7fd 100644
--- a/Documentation/ABI/testing/sysfs-kernel-iommu_groups
+++ b/Documentation/ABI/testing/sysfs-kernel-iommu_groups
@@ -33,3 +33,32 @@ Description:    In case an RMRR is used only by graphics or USB devices
 		it is now exposed as "direct-relaxable" instead of "direct".
 		In device assignment use case, for instance, those RMRR
 		are considered to be relaxable and safe.
+
+What:		/sys/kernel/iommu_groups/<grp_id>/type
+Date:		November 2020
+KernelVersion:	v5.11
+Contact:	Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>
+Description:	/sys/kernel/iommu_groups/<grp_id>/type shows the type of default
+		domain in use by iommu for this group. See include/linux/iommu.h
+		for possible values. A privileged user could request kernel to
+		change the group type by writing to this file. Presently, only
+		three types of request are supported:
+		1. DMA: All the DMA transactions from the device in this group
+			are translated by the iommu.
+		2. identity: All the DMA transactions from the device in this
+			     group are *not* translated by the iommu.
+		3. auto: Change to the type the device was booted with.
+		Note:
+		-----
+		The default domain type of a group may be modified only when
+		1. The group has *only* one device
+		2. The device in the group is not bound to any device driver.
+		   So, the users must unbind the appropriate driver before
+		   changing the default domain type.
+		Caution:
+		--------
+		Unbinding a device driver will take away the driver's control
+		over the device and if done on devices that host root file
+		system could lead to catastrophic effects (the users might
+		need to reboot the machine to get it to normal state). So, it's
+		expected that the users understand what they're doing.
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v9 1/4] iommu: Move def_domain type check for untrusted device into core
  2020-11-21 13:56 ` [PATCH v9 1/4] iommu: Move def_domain type check for untrusted device into core Lu Baolu
@ 2020-11-23 12:04   ` Will Deacon
  2020-11-23 12:55     ` Lu Baolu
  0 siblings, 1 reply; 10+ messages in thread
From: Will Deacon @ 2020-11-23 12:04 UTC (permalink / raw)
  To: Lu Baolu
  Cc: Joerg Roedel, Ashok Raj, Christoph Hellwig, Sohil Mehta,
	Robin Murphy, Jacob Pan, iommu, linux-kernel,
	Shameerali Kolothum Thodi

On Sat, Nov 21, 2020 at 09:56:17PM +0800, Lu Baolu wrote:
> So that the vendor iommu drivers are no more required to provide the
> def_domain_type callback to always isolate the untrusted devices.
> 
> Link: https://lore.kernel.org/linux-iommu/243ce89c33fe4b9da4c56ba35acebf81@huawei.com/
> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
> ---
>  drivers/iommu/intel/iommu.c |  7 -------
>  drivers/iommu/iommu.c       | 21 ++++++++++++++-------
>  2 files changed, 14 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index af3abd285214..6711f78141a4 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -2916,13 +2916,6 @@ static int device_def_domain_type(struct device *dev)
>  	if (dev_is_pci(dev)) {
>  		struct pci_dev *pdev = to_pci_dev(dev);
>  
> -		/*
> -		 * Prevent any device marked as untrusted from getting
> -		 * placed into the statically identity mapping domain.
> -		 */
> -		if (pdev->untrusted)
> -			return IOMMU_DOMAIN_DMA;
> -
>  		if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
>  			return IOMMU_DOMAIN_IDENTITY;
>  
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index 88b0c9192d8c..3256784c0358 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -1457,13 +1457,23 @@ struct iommu_group *fsl_mc_device_group(struct device *dev)
>  }
>  EXPORT_SYMBOL_GPL(fsl_mc_device_group);
>  
> -static int iommu_get_def_domain_type(struct device *dev)
> +/* Get the mandatary def_domain type for device. Otherwise, return 0. */
> +static int iommu_get_mandatory_def_domain_type(struct device *dev)
>  {
>  	const struct iommu_ops *ops = dev->bus->iommu_ops;
> -	unsigned int type = 0;
> +
> +	if (dev_is_pci(dev) && to_pci_dev(dev)->untrusted)
> +		return IOMMU_DOMAIN_DMA;
>  
>  	if (ops->def_domain_type)
> -		type = ops->def_domain_type(dev);
> +		return ops->def_domain_type(dev);
> +
> +	return 0;
> +}
> +
> +static int iommu_get_def_domain_type(struct device *dev)
> +{
> +	int type = iommu_get_mandatory_def_domain_type(dev);
>  
>  	return (type == 0) ? iommu_def_domain_type : type;
>  }
> @@ -1645,13 +1655,10 @@ struct __group_domain_type {
>  
>  static int probe_get_default_domain_type(struct device *dev, void *data)
>  {
> -	const struct iommu_ops *ops = dev->bus->iommu_ops;
>  	struct __group_domain_type *gtype = data;
>  	unsigned int type = 0;
>  
> -	if (ops->def_domain_type)
> -		type = ops->def_domain_type(dev);
> -
> +	type = iommu_get_mandatory_def_domain_type(dev);

afaict, this code is only called from probe_alloc_default_domain(), which
has:

        /* Ask for default domain requirements of all devices in the group */
        __iommu_group_for_each_dev(group, &gtype,
                                   probe_get_default_domain_type);

        if (!gtype.type)
                gtype.type = iommu_def_domain_type;

so is there actually a need to introduce the new
iommu_get_mandatory_def_domain_type() function, given that a type of 0
always ends up resolving to the default domain type?

Will

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v9 1/4] iommu: Move def_domain type check for untrusted device into core
  2020-11-23 12:04   ` Will Deacon
@ 2020-11-23 12:55     ` Lu Baolu
  2020-11-23 13:03       ` Will Deacon
  0 siblings, 1 reply; 10+ messages in thread
From: Lu Baolu @ 2020-11-23 12:55 UTC (permalink / raw)
  To: Will Deacon
  Cc: baolu.lu, Joerg Roedel, Ashok Raj, Christoph Hellwig,
	Sohil Mehta, Robin Murphy, Jacob Pan, iommu, linux-kernel,
	Shameerali Kolothum Thodi

Hi Will,

On 2020/11/23 20:04, Will Deacon wrote:
> On Sat, Nov 21, 2020 at 09:56:17PM +0800, Lu Baolu wrote:
>> So that the vendor iommu drivers are no more required to provide the
>> def_domain_type callback to always isolate the untrusted devices.
>>
>> Link: https://lore.kernel.org/linux-iommu/243ce89c33fe4b9da4c56ba35acebf81@huawei.com/
>> Cc: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
>> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
>> ---
>>   drivers/iommu/intel/iommu.c |  7 -------
>>   drivers/iommu/iommu.c       | 21 ++++++++++++++-------
>>   2 files changed, 14 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
>> index af3abd285214..6711f78141a4 100644
>> --- a/drivers/iommu/intel/iommu.c
>> +++ b/drivers/iommu/intel/iommu.c
>> @@ -2916,13 +2916,6 @@ static int device_def_domain_type(struct device *dev)
>>   	if (dev_is_pci(dev)) {
>>   		struct pci_dev *pdev = to_pci_dev(dev);
>>   
>> -		/*
>> -		 * Prevent any device marked as untrusted from getting
>> -		 * placed into the statically identity mapping domain.
>> -		 */
>> -		if (pdev->untrusted)
>> -			return IOMMU_DOMAIN_DMA;
>> -
>>   		if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
>>   			return IOMMU_DOMAIN_IDENTITY;
>>   
>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
>> index 88b0c9192d8c..3256784c0358 100644
>> --- a/drivers/iommu/iommu.c
>> +++ b/drivers/iommu/iommu.c
>> @@ -1457,13 +1457,23 @@ struct iommu_group *fsl_mc_device_group(struct device *dev)
>>   }
>>   EXPORT_SYMBOL_GPL(fsl_mc_device_group);
>>   
>> -static int iommu_get_def_domain_type(struct device *dev)
>> +/* Get the mandatary def_domain type for device. Otherwise, return 0. */
>> +static int iommu_get_mandatory_def_domain_type(struct device *dev)
>>   {
>>   	const struct iommu_ops *ops = dev->bus->iommu_ops;
>> -	unsigned int type = 0;
>> +
>> +	if (dev_is_pci(dev) && to_pci_dev(dev)->untrusted)
>> +		return IOMMU_DOMAIN_DMA;
>>   
>>   	if (ops->def_domain_type)
>> -		type = ops->def_domain_type(dev);
>> +		return ops->def_domain_type(dev);
>> +
>> +	return 0;
>> +}
>> +
>> +static int iommu_get_def_domain_type(struct device *dev)
>> +{
>> +	int type = iommu_get_mandatory_def_domain_type(dev);
>>   
>>   	return (type == 0) ? iommu_def_domain_type : type;
>>   }
>> @@ -1645,13 +1655,10 @@ struct __group_domain_type {
>>   
>>   static int probe_get_default_domain_type(struct device *dev, void *data)
>>   {
>> -	const struct iommu_ops *ops = dev->bus->iommu_ops;
>>   	struct __group_domain_type *gtype = data;
>>   	unsigned int type = 0;
>>   
>> -	if (ops->def_domain_type)
>> -		type = ops->def_domain_type(dev);
>> -
>> +	type = iommu_get_mandatory_def_domain_type(dev);
> 
> afaict, this code is only called from probe_alloc_default_domain(), which
> has:
> 
>          /* Ask for default domain requirements of all devices in the group */
>          __iommu_group_for_each_dev(group, &gtype,
>                                     probe_get_default_domain_type);
> 
>          if (!gtype.type)
>                  gtype.type = iommu_def_domain_type;
> 
> so is there actually a need to introduce the new
> iommu_get_mandatory_def_domain_type() function, given that a type of 0
> always ends up resolving to the default domain type?

Another consumer of this helper is in the next patch:

+	dev_def_dom = iommu_get_mandatory_def_domain_type(dev);
+
+	/* Check if user requested domain is supported by the device or not */
+	if (!type) {
+		/*
+		 * If the user hasn't requested any specific type of domain and
+		 * if the device supports both the domains, then default to the
+		 * domain the device was booted with
+		 */
+		type = iommu_get_def_domain_type(dev);
+	} else if (dev_def_dom && type != dev_def_dom) {
+		dev_err_ratelimited(prev_dev, "Device cannot be in %s domain\n",
+				    iommu_domain_type_str(type));
+		ret = -EINVAL;
+		goto out;
+	}

I also added the untrusted device check in
iommu_get_mandatory_def_domain_type(), so that we don't need to care
about this in multiple places.

Best regards,
baolu

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v9 1/4] iommu: Move def_domain type check for untrusted device into core
  2020-11-23 12:55     ` Lu Baolu
@ 2020-11-23 13:03       ` Will Deacon
  2020-11-23 13:54         ` Lu Baolu
  0 siblings, 1 reply; 10+ messages in thread
From: Will Deacon @ 2020-11-23 13:03 UTC (permalink / raw)
  To: Lu Baolu
  Cc: Joerg Roedel, Ashok Raj, Christoph Hellwig, Sohil Mehta,
	Robin Murphy, Jacob Pan, iommu, linux-kernel,
	Shameerali Kolothum Thodi

Hi Baolu,

On Mon, Nov 23, 2020 at 08:55:17PM +0800, Lu Baolu wrote:
> On 2020/11/23 20:04, Will Deacon wrote:
> > On Sat, Nov 21, 2020 at 09:56:17PM +0800, Lu Baolu wrote:
> > > @@ -1645,13 +1655,10 @@ struct __group_domain_type {
> > >   static int probe_get_default_domain_type(struct device *dev, void *data)
> > >   {
> > > -	const struct iommu_ops *ops = dev->bus->iommu_ops;
> > >   	struct __group_domain_type *gtype = data;
> > >   	unsigned int type = 0;
> > > -	if (ops->def_domain_type)
> > > -		type = ops->def_domain_type(dev);
> > > -
> > > +	type = iommu_get_mandatory_def_domain_type(dev);
> > 
> > afaict, this code is only called from probe_alloc_default_domain(), which
> > has:
> > 
> >          /* Ask for default domain requirements of all devices in the group */
> >          __iommu_group_for_each_dev(group, &gtype,
> >                                     probe_get_default_domain_type);
> > 
> >          if (!gtype.type)
> >                  gtype.type = iommu_def_domain_type;
> > 
> > so is there actually a need to introduce the new
> > iommu_get_mandatory_def_domain_type() function, given that a type of 0
> > always ends up resolving to the default domain type?
> 
> Another consumer of this helper is in the next patch:
> 
> +	dev_def_dom = iommu_get_mandatory_def_domain_type(dev);
> +
> +	/* Check if user requested domain is supported by the device or not */
> +	if (!type) {
> +		/*
> +		 * If the user hasn't requested any specific type of domain and
> +		 * if the device supports both the domains, then default to the
> +		 * domain the device was booted with
> +		 */
> +		type = iommu_get_def_domain_type(dev);
> +	} else if (dev_def_dom && type != dev_def_dom) {
> +		dev_err_ratelimited(prev_dev, "Device cannot be in %s domain\n",
> +				    iommu_domain_type_str(type));
> +		ret = -EINVAL;
> +		goto out;
> +	}
> 
> I also added the untrusted device check in
> iommu_get_mandatory_def_domain_type(), so that we don't need to care
> about this in multiple places.

I see, but isn't this also setting the default domain type in the case that
it gets back a type of 0? I think it would be nice to avoid having both
iommu_get_mandatory_def_domain_type() and iommu_get_def_domain_type() of we
can, as it's really not clear which one to use when and what is meant by
"mandatory" imo.

Will

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v9 1/4] iommu: Move def_domain type check for untrusted device into core
  2020-11-23 13:03       ` Will Deacon
@ 2020-11-23 13:54         ` Lu Baolu
  2020-11-23 14:03           ` Will Deacon
  0 siblings, 1 reply; 10+ messages in thread
From: Lu Baolu @ 2020-11-23 13:54 UTC (permalink / raw)
  To: Will Deacon
  Cc: baolu.lu, Joerg Roedel, Ashok Raj, Christoph Hellwig,
	Sohil Mehta, Robin Murphy, Jacob Pan, iommu, linux-kernel,
	Shameerali Kolothum Thodi

Hi Will,

On 2020/11/23 21:03, Will Deacon wrote:
> Hi Baolu,
> 
> On Mon, Nov 23, 2020 at 08:55:17PM +0800, Lu Baolu wrote:
>> On 2020/11/23 20:04, Will Deacon wrote:
>>> On Sat, Nov 21, 2020 at 09:56:17PM +0800, Lu Baolu wrote:
>>>> @@ -1645,13 +1655,10 @@ struct __group_domain_type {
>>>>    static int probe_get_default_domain_type(struct device *dev, void *data)
>>>>    {
>>>> -	const struct iommu_ops *ops = dev->bus->iommu_ops;
>>>>    	struct __group_domain_type *gtype = data;
>>>>    	unsigned int type = 0;
>>>> -	if (ops->def_domain_type)
>>>> -		type = ops->def_domain_type(dev);
>>>> -
>>>> +	type = iommu_get_mandatory_def_domain_type(dev);
>>>
>>> afaict, this code is only called from probe_alloc_default_domain(), which
>>> has:
>>>
>>>           /* Ask for default domain requirements of all devices in the group */
>>>           __iommu_group_for_each_dev(group, &gtype,
>>>                                      probe_get_default_domain_type);
>>>
>>>           if (!gtype.type)
>>>                   gtype.type = iommu_def_domain_type;
>>>
>>> so is there actually a need to introduce the new
>>> iommu_get_mandatory_def_domain_type() function, given that a type of 0
>>> always ends up resolving to the default domain type?
>>
>> Another consumer of this helper is in the next patch:
>>
>> +	dev_def_dom = iommu_get_mandatory_def_domain_type(dev);
>> +
>> +	/* Check if user requested domain is supported by the device or not */
>> +	if (!type) {
>> +		/*
>> +		 * If the user hasn't requested any specific type of domain and
>> +		 * if the device supports both the domains, then default to the
>> +		 * domain the device was booted with
>> +		 */
>> +		type = iommu_get_def_domain_type(dev);
>> +	} else if (dev_def_dom && type != dev_def_dom) {
>> +		dev_err_ratelimited(prev_dev, "Device cannot be in %s domain\n",
>> +				    iommu_domain_type_str(type));
>> +		ret = -EINVAL;
>> +		goto out;
>> +	}
>>
>> I also added the untrusted device check in
>> iommu_get_mandatory_def_domain_type(), so that we don't need to care
>> about this in multiple places.
> 
> I see, but isn't this also setting the default domain type in the case that
> it gets back a type of 0? I think it would be nice to avoid having both
> iommu_get_mandatory_def_domain_type() and iommu_get_def_domain_type() of we
> can, as it's really not clear which one to use when and what is meant by
> "mandatory" imo.

Yes, agreed. I will remove iommu_get_mandatory_def_domain_type() and
keep iommu_get_def_domain_type() as the only helper in the next version.

Best regards,
baolu

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v9 1/4] iommu: Move def_domain type check for untrusted device into core
  2020-11-23 13:54         ` Lu Baolu
@ 2020-11-23 14:03           ` Will Deacon
  0 siblings, 0 replies; 10+ messages in thread
From: Will Deacon @ 2020-11-23 14:03 UTC (permalink / raw)
  To: Lu Baolu
  Cc: Joerg Roedel, Ashok Raj, Christoph Hellwig, Sohil Mehta,
	Robin Murphy, Jacob Pan, iommu, linux-kernel,
	Shameerali Kolothum Thodi

On Mon, Nov 23, 2020 at 09:54:49PM +0800, Lu Baolu wrote:
> Hi Will,
> 
> On 2020/11/23 21:03, Will Deacon wrote:
> > Hi Baolu,
> > 
> > On Mon, Nov 23, 2020 at 08:55:17PM +0800, Lu Baolu wrote:
> > > On 2020/11/23 20:04, Will Deacon wrote:
> > > > On Sat, Nov 21, 2020 at 09:56:17PM +0800, Lu Baolu wrote:
> > > > > @@ -1645,13 +1655,10 @@ struct __group_domain_type {
> > > > >    static int probe_get_default_domain_type(struct device *dev, void *data)
> > > > >    {
> > > > > -	const struct iommu_ops *ops = dev->bus->iommu_ops;
> > > > >    	struct __group_domain_type *gtype = data;
> > > > >    	unsigned int type = 0;
> > > > > -	if (ops->def_domain_type)
> > > > > -		type = ops->def_domain_type(dev);
> > > > > -
> > > > > +	type = iommu_get_mandatory_def_domain_type(dev);
> > > > 
> > > > afaict, this code is only called from probe_alloc_default_domain(), which
> > > > has:
> > > > 
> > > >           /* Ask for default domain requirements of all devices in the group */
> > > >           __iommu_group_for_each_dev(group, &gtype,
> > > >                                      probe_get_default_domain_type);
> > > > 
> > > >           if (!gtype.type)
> > > >                   gtype.type = iommu_def_domain_type;
> > > > 
> > > > so is there actually a need to introduce the new
> > > > iommu_get_mandatory_def_domain_type() function, given that a type of 0
> > > > always ends up resolving to the default domain type?
> > > 
> > > Another consumer of this helper is in the next patch:
> > > 
> > > +	dev_def_dom = iommu_get_mandatory_def_domain_type(dev);
> > > +
> > > +	/* Check if user requested domain is supported by the device or not */
> > > +	if (!type) {
> > > +		/*
> > > +		 * If the user hasn't requested any specific type of domain and
> > > +		 * if the device supports both the domains, then default to the
> > > +		 * domain the device was booted with
> > > +		 */
> > > +		type = iommu_get_def_domain_type(dev);
> > > +	} else if (dev_def_dom && type != dev_def_dom) {
> > > +		dev_err_ratelimited(prev_dev, "Device cannot be in %s domain\n",
> > > +				    iommu_domain_type_str(type));
> > > +		ret = -EINVAL;
> > > +		goto out;
> > > +	}
> > > 
> > > I also added the untrusted device check in
> > > iommu_get_mandatory_def_domain_type(), so that we don't need to care
> > > about this in multiple places.
> > 
> > I see, but isn't this also setting the default domain type in the case that
> > it gets back a type of 0? I think it would be nice to avoid having both
> > iommu_get_mandatory_def_domain_type() and iommu_get_def_domain_type() of we
> > can, as it's really not clear which one to use when and what is meant by
> > "mandatory" imo.
> 
> Yes, agreed. I will remove iommu_get_mandatory_def_domain_type() and
> keep iommu_get_def_domain_type() as the only helper in the next version.

Great, thanks!

Will

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-11-23 14:03 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-21 13:56 [PATCH v9 0/4] iommu: Add support to change default domain of Lu Baolu
2020-11-21 13:56 ` [PATCH v9 1/4] iommu: Move def_domain type check for untrusted device into core Lu Baolu
2020-11-23 12:04   ` Will Deacon
2020-11-23 12:55     ` Lu Baolu
2020-11-23 13:03       ` Will Deacon
2020-11-23 13:54         ` Lu Baolu
2020-11-23 14:03           ` Will Deacon
2020-11-21 13:56 ` [PATCH v9 2/4] iommu: Add support to change default domain of an iommu group Lu Baolu
2020-11-21 13:56 ` [PATCH v9 3/4] iommu: Take lock before reading iommu group default domain type Lu Baolu
2020-11-21 13:56 ` [PATCH v9 4/4] iommu: Document usage of "/sys/kernel/iommu_groups/<grp_id>/type" file Lu Baolu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).