mirror of https://gitee.com/openkylin/linux.git
Merge branch 'for-next/iommu/default-domains' into for-next/iommu/core
Support for changing the default domain type for singleton IOMMU groups via sysfs when the constituent device is not already bound to a device driver. * for-next/iommu/default-domains: iommu: Fix htmldocs warnings in sysfs-kernel-iommu_groups iommu: Document usage of "/sys/kernel/iommu_groups/<grp_id>/type" file iommu: Take lock before reading iommu group default domain type iommu: Add support to change default domain of an iommu group iommu: Move def_domain type check for untrusted device into core
This commit is contained in:
commit
33f974dbaa
|
@ -33,3 +33,33 @@ 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 read values. A privileged user could request kernel to
|
||||
change the group type by writing to this file. Valid write values:
|
||||
|
||||
======== ======================================================
|
||||
DMA All the DMA transactions from the device in this group
|
||||
are translated by the iommu.
|
||||
identity All the DMA transactions from the device in this group
|
||||
are not translated by the iommu.
|
||||
auto Change to the type the device was booted with.
|
||||
======== ======================================================
|
||||
|
||||
The default domain type of a group may be modified only when
|
||||
|
||||
- The group has only one device.
|
||||
- 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.
|
||||
|
||||
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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 = \
|
||||
|
@ -499,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:
|
||||
|
@ -515,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);
|
||||
|
@ -525,7 +529,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)
|
||||
{
|
||||
|
@ -1460,12 +1465,14 @@ EXPORT_SYMBOL_GPL(fsl_mc_device_group);
|
|||
static int iommu_get_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 (type == 0) ? iommu_def_domain_type : type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iommu_group_alloc_default_domain(struct bus_type *bus,
|
||||
|
@ -1507,7 +1514,7 @@ static int iommu_alloc_default_domain(struct iommu_group *group,
|
|||
if (group->default_domain)
|
||||
return 0;
|
||||
|
||||
type = iommu_get_def_domain_type(dev);
|
||||
type = iommu_get_def_domain_type(dev) ? : iommu_def_domain_type;
|
||||
|
||||
return iommu_group_alloc_default_domain(dev->bus, group, type);
|
||||
}
|
||||
|
@ -1645,12 +1652,8 @@ 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);
|
||||
unsigned int type = iommu_get_def_domain_type(dev);
|
||||
|
||||
if (type) {
|
||||
if (gtype->type && gtype->type != type) {
|
||||
|
@ -3029,3 +3032,228 @@ 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_def_domain_type(dev);
|
||||
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 = dev_def_dom ? : iommu_def_domain_type;
|
||||
} 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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue