提交 44d6e907 编写于 作者: H Hongbo Yao 提交者: Xie XiuQi

Revert "vfio: relieve mmap_sem reader cacheline bouncing by holding it longer"

hulk inclusion
category: bugfix
bugzilla: 27970
CVE: NA

-------------------------------------------------

This reverts commit 038c2f6d971260670b0844208f4e3424b1d55c39.
If we do hotplug in vfio-enabled kvm, holding the mmap_sem reader longer
will cause hangtask.

[ 1091.426125] Call trace:
[ 1091.428572]  __switch_to+0xe4/0x148
[ 1091.432054]  __schedule+0x31c/0x9c0
[ 1091.435528]  schedule+0x2c/0x88
[ 1091.438660]  rwsem_down_write_failed+0x138/0x2e8
[ 1091.443261]  down_write+0x58/0x70
[ 1091.446569]  vaddr_get_pfn+0x54/0x280 [vfio_iommu_type1]
[ 1091.451863]  vfio_pin_pages_remote+0x88/0x3c0 [vfio_iommu_type1]
[ 1091.457848]  vfio_pin_map_dma+0xc0/0x300 [vfio_iommu_type1]
[ 1091.463401]  vfio_iommu_type1_ioctl+0xa5c/0xcc4 [vfio_iommu_type1]
[ 1091.469563]  vfio_fops_unl_ioctl+0x74/0x2e0 [vfio]
[ 1091.474338]  do_vfs_ioctl+0xc4/0x8c0
[ 1091.477904]  ksys_ioctl+0x8c/0xa0
[ 1091.481210]  __arm64_sys_ioctl+0x28/0x38
[ 1091.485121]  el0_svc_common+0x78/0x130
[ 1091.488860]  el0_svc_handler+0x38/0x78
[ 1091.492598]  el0_svc+0x8/0xc
Signed-off-by: NHongbo Yao <yaohongbo@huawei.com>
Reviewed-By: NXie XiuQi <xiexiuqi@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NXie XiuQi <xiexiuqi@huawei.com>
上级 cf975ca6
......@@ -347,7 +347,7 @@ static int put_pfn(unsigned long pfn, int prot)
}
static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
int prot, unsigned long *pfn, bool handle_mmap_sem)
int prot, unsigned long *pfn)
{
struct page *page[1];
struct vm_area_struct *vma;
......@@ -358,8 +358,7 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
if (prot & IOMMU_WRITE)
flags |= FOLL_WRITE;
if (handle_mmap_sem)
down_read(&mm->mmap_sem);
down_read(&mm->mmap_sem);
if (mm == current->mm) {
ret = get_user_pages_longterm(vaddr, 1, flags, page, vmas);
} else {
......@@ -377,16 +376,14 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
put_page(page[0]);
}
}
if (handle_mmap_sem)
up_read(&mm->mmap_sem);
up_read(&mm->mmap_sem);
if (ret == 1) {
*pfn = page_to_pfn(page[0]);
return 0;
}
if (handle_mmap_sem)
down_read(&mm->mmap_sem);
down_read(&mm->mmap_sem);
vma = find_vma_intersection(mm, vaddr, vaddr + 1);
......@@ -396,8 +393,7 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
ret = 0;
}
if (handle_mmap_sem)
up_read(&mm->mmap_sem);
up_read(&mm->mmap_sem);
return ret;
}
......@@ -419,12 +415,9 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
if (!mm)
return -ENODEV;
down_read(&mm->mmap_sem);
ret = vaddr_get_pfn(mm, vaddr, dma->prot, pfn_base, false);
if (ret) {
up_read(&mm->mmap_sem);
ret = vaddr_get_pfn(mm, vaddr, dma->prot, pfn_base);
if (ret)
return ret;
}
pinned++;
rsvd = is_invalid_reserved_pfn(*pfn_base);
......@@ -439,7 +432,6 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
put_pfn(*pfn_base, dma->prot);
pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", __func__,
limit << PAGE_SHIFT);
up_read(&mm->mmap_sem);
return -ENOMEM;
}
lock_acct++;
......@@ -451,7 +443,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
/* Lock all the consecutive pages from pfn_base */
for (vaddr += PAGE_SIZE, iova += PAGE_SIZE; pinned < npage;
pinned++, vaddr += PAGE_SIZE, iova += PAGE_SIZE) {
ret = vaddr_get_pfn(mm, vaddr, dma->prot, &pfn, false);
ret = vaddr_get_pfn(mm, vaddr, dma->prot, &pfn);
if (ret)
break;
......@@ -468,7 +460,6 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n",
__func__, limit << PAGE_SHIFT);
ret = -ENOMEM;
up_read(&mm->mmap_sem);
goto unpin_out;
}
lock_acct++;
......@@ -476,7 +467,6 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
}
out:
up_read(&mm->mmap_sem);
ret = vfio_lock_acct(dma, lock_acct, false);
unpin_out:
......@@ -523,7 +513,7 @@ static int vfio_pin_page_external(struct vfio_dma *dma, unsigned long vaddr,
if (!mm)
return -ENODEV;
ret = vaddr_get_pfn(mm, vaddr, dma->prot, pfn_base, true);
ret = vaddr_get_pfn(mm, vaddr, dma->prot, pfn_base);
if (!ret && do_accounting && !is_invalid_reserved_pfn(*pfn_base)) {
ret = vfio_lock_acct(dma, 1, true);
if (ret) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册