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

iommu/amd: Lock code paths traversing protection_domain->dev_list

fix #26319040

commit 2a78f9962565e53b78363eaf516eb052009e8020 upstream.

The traversing of this list requires protection_domain->lock to be taken
to avoid nasty races with attach/detach code. Make sure the lock is held
on all code-paths traversing this list.
Reported-by: NFilippo Sironi <sironi@amazon.de>
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>
上级 30061d95
...@@ -1538,8 +1538,13 @@ static int iommu_map_page(struct protection_domain *dom, ...@@ -1538,8 +1538,13 @@ static int iommu_map_page(struct protection_domain *dom,
ret = 0; ret = 0;
out: out:
if (updated) if (updated) {
unsigned long flags;
spin_lock_irqsave(&dom->lock, flags);
update_domain(dom); update_domain(dom);
spin_unlock_irqrestore(&dom->lock, flags);
}
return ret; return ret;
} }
...@@ -1778,8 +1783,12 @@ static void free_gcr3_table(struct protection_domain *domain) ...@@ -1778,8 +1783,12 @@ static void free_gcr3_table(struct protection_domain *domain)
static void dma_ops_domain_flush_tlb(struct dma_ops_domain *dom) static void dma_ops_domain_flush_tlb(struct dma_ops_domain *dom)
{ {
unsigned long flags;
spin_lock_irqsave(&dom->domain.lock, flags);
domain_flush_tlb(&dom->domain); domain_flush_tlb(&dom->domain);
domain_flush_complete(&dom->domain); domain_flush_complete(&dom->domain);
spin_unlock_irqrestore(&dom->domain.lock, flags);
} }
static void iova_domain_flush_tlb(struct iova_domain *iovad) static void iova_domain_flush_tlb(struct iova_domain *iovad)
...@@ -2357,6 +2366,7 @@ static dma_addr_t __map_single(struct device *dev, ...@@ -2357,6 +2366,7 @@ static dma_addr_t __map_single(struct device *dev,
{ {
dma_addr_t offset = paddr & ~PAGE_MASK; dma_addr_t offset = paddr & ~PAGE_MASK;
dma_addr_t address, start, ret; dma_addr_t address, start, ret;
unsigned long flags;
unsigned int pages; unsigned int pages;
int prot = 0; int prot = 0;
int i; int i;
...@@ -2397,8 +2407,10 @@ static dma_addr_t __map_single(struct device *dev, ...@@ -2397,8 +2407,10 @@ static dma_addr_t __map_single(struct device *dev,
iommu_unmap_page(&dma_dom->domain, start, PAGE_SIZE); iommu_unmap_page(&dma_dom->domain, start, PAGE_SIZE);
} }
spin_lock_irqsave(&dma_dom->domain.lock, flags);
domain_flush_tlb(&dma_dom->domain); domain_flush_tlb(&dma_dom->domain);
domain_flush_complete(&dma_dom->domain); domain_flush_complete(&dma_dom->domain);
spin_unlock_irqrestore(&dma_dom->domain.lock, flags);
dma_ops_free_iova(dma_dom, address, pages); dma_ops_free_iova(dma_dom, address, pages);
...@@ -2427,8 +2439,12 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, ...@@ -2427,8 +2439,12 @@ static void __unmap_single(struct dma_ops_domain *dma_dom,
} }
if (amd_iommu_unmap_flush) { if (amd_iommu_unmap_flush) {
unsigned long flags;
spin_lock_irqsave(&dma_dom->domain.lock, flags);
domain_flush_tlb(&dma_dom->domain); domain_flush_tlb(&dma_dom->domain);
domain_flush_complete(&dma_dom->domain); domain_flush_complete(&dma_dom->domain);
spin_unlock_irqrestore(&dma_dom->domain.lock, flags);
dma_ops_free_iova(dma_dom, dma_addr, pages); dma_ops_free_iova(dma_dom, dma_addr, pages);
} else { } else {
pages = __roundup_pow_of_two(pages); pages = __roundup_pow_of_two(pages);
...@@ -3200,9 +3216,12 @@ static bool amd_iommu_is_attach_deferred(struct iommu_domain *domain, ...@@ -3200,9 +3216,12 @@ static bool amd_iommu_is_attach_deferred(struct iommu_domain *domain,
static void amd_iommu_flush_iotlb_all(struct iommu_domain *domain) static void amd_iommu_flush_iotlb_all(struct iommu_domain *domain)
{ {
struct protection_domain *dom = to_pdomain(domain); struct protection_domain *dom = to_pdomain(domain);
unsigned long flags;
spin_lock_irqsave(&dom->lock, flags);
domain_flush_tlb_pde(dom); domain_flush_tlb_pde(dom);
domain_flush_complete(dom); domain_flush_complete(dom);
spin_unlock_irqrestore(&dom->lock, flags);
} }
static void amd_iommu_iotlb_range_add(struct iommu_domain *domain, static void amd_iommu_iotlb_range_add(struct iommu_domain *domain,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册