提交 30061d95 编写于 作者: J Joerg Roedel 提交者: Shile Zhang

iommu/amd: Lock dev_data in attach/detach code paths

fix #26319040

commit ab7b2577f0d119052b98b8d913bad369ac2760eb upstream.

Make sure that attaching a detaching a device can't race against each
other and protect the iommu_dev_data with a spin_lock in these code
paths.

Fixes: 92d420ec ("iommu/amd: Relax locking in dma_ops path")
Reviewed-by: NFilippo Sironi <sironi@amazon.de>
Reviewed-by: NJerry Snitselaar <jsnitsel@redhat.com>
Signed-off-by: NJoerg Roedel <jroedel@suse.de>
Signed-off-by: Ntianyi <fujunkang@linux.alibaba.com>
Reviewed-by: Nzhangliguang <zhangliguang@linux.alibaba.com>
Acked-by: Nzhangliguang <zhangliguang@linux.alibaba.com>
上级 9fcb8428
...@@ -210,6 +210,7 @@ static struct iommu_dev_data *alloc_dev_data(u16 devid) ...@@ -210,6 +210,7 @@ static struct iommu_dev_data *alloc_dev_data(u16 devid)
if (!dev_data) if (!dev_data)
return NULL; return NULL;
spin_lock_init(&dev_data->lock);
dev_data->devid = devid; dev_data->devid = devid;
ratelimit_default_init(&dev_data->rs); ratelimit_default_init(&dev_data->rs);
...@@ -2099,6 +2100,8 @@ static int attach_device(struct device *dev, ...@@ -2099,6 +2100,8 @@ static int attach_device(struct device *dev,
dev_data = get_dev_data(dev); dev_data = get_dev_data(dev);
spin_lock(&dev_data->lock);
ret = -EBUSY; ret = -EBUSY;
if (dev_data->domain != NULL) if (dev_data->domain != NULL)
goto out; goto out;
...@@ -2141,6 +2144,8 @@ static int attach_device(struct device *dev, ...@@ -2141,6 +2144,8 @@ static int attach_device(struct device *dev,
domain_flush_complete(domain); domain_flush_complete(domain);
out: out:
spin_unlock(&dev_data->lock);
spin_unlock_irqrestore(&domain->lock, flags); spin_unlock_irqrestore(&domain->lock, flags);
return ret; return ret;
...@@ -2160,6 +2165,8 @@ static void detach_device(struct device *dev) ...@@ -2160,6 +2165,8 @@ static void detach_device(struct device *dev)
spin_lock_irqsave(&domain->lock, flags); spin_lock_irqsave(&domain->lock, flags);
spin_lock(&dev_data->lock);
/* /*
* First check if the device is still attached. It might already * First check if the device is still attached. It might already
* be detached from its domain because the generic * be detached from its domain because the generic
...@@ -2182,6 +2189,8 @@ static void detach_device(struct device *dev) ...@@ -2182,6 +2189,8 @@ static void detach_device(struct device *dev)
dev_data->ats.enabled = false; dev_data->ats.enabled = false;
out: out:
spin_unlock(&dev_data->lock);
spin_unlock_irqrestore(&domain->lock, flags); spin_unlock_irqrestore(&domain->lock, flags);
} }
......
...@@ -635,6 +635,9 @@ struct devid_map { ...@@ -635,6 +635,9 @@ struct devid_map {
* This struct contains device specific data for the IOMMU * This struct contains device specific data for the IOMMU
*/ */
struct iommu_dev_data { struct iommu_dev_data {
/*Protect against attach/detach races */
spinlock_t lock;
struct list_head list; /* For domain->dev_list */ struct list_head list; /* For domain->dev_list */
struct llist_node dev_data_list; /* For global dev_data_list */ struct llist_node dev_data_list; /* For global dev_data_list */
struct protection_domain *domain; /* Domain the device is bound to */ struct protection_domain *domain; /* Domain the device is bound to */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册