diff options
| -rw-r--r-- | drivers/vfio/vfio_iommu_type1.c | 25 |
1 files changed, 10 insertions, 15 deletions
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 5c212bf29640..3c082451ab1a 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c | |||
| @@ -404,6 +404,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr, | |||
| 404 | { | 404 | { |
| 405 | unsigned long pfn = 0; | 405 | unsigned long pfn = 0; |
| 406 | long ret, pinned = 0, lock_acct = 0; | 406 | long ret, pinned = 0, lock_acct = 0; |
| 407 | bool rsvd; | ||
| 407 | dma_addr_t iova = vaddr - dma->vaddr + dma->iova; | 408 | dma_addr_t iova = vaddr - dma->vaddr + dma->iova; |
| 408 | 409 | ||
| 409 | /* This code path is only user initiated */ | 410 | /* This code path is only user initiated */ |
| @@ -414,23 +415,14 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr, | |||
| 414 | if (ret) | 415 | if (ret) |
| 415 | return ret; | 416 | return ret; |
| 416 | 417 | ||
| 417 | if (is_invalid_reserved_pfn(*pfn_base)) { | ||
| 418 | struct vm_area_struct *vma; | ||
| 419 | |||
| 420 | down_read(¤t->mm->mmap_sem); | ||
| 421 | vma = find_vma_intersection(current->mm, vaddr, vaddr + 1); | ||
| 422 | pinned = min_t(long, npage, vma_pages(vma)); | ||
| 423 | up_read(¤t->mm->mmap_sem); | ||
| 424 | return pinned; | ||
| 425 | } | ||
| 426 | |||
| 427 | pinned++; | 418 | pinned++; |
| 419 | rsvd = is_invalid_reserved_pfn(*pfn_base); | ||
| 428 | 420 | ||
| 429 | /* | 421 | /* |
| 430 | * Reserved pages aren't counted against the user, externally pinned | 422 | * Reserved pages aren't counted against the user, externally pinned |
| 431 | * pages are already counted against the user. | 423 | * pages are already counted against the user. |
| 432 | */ | 424 | */ |
| 433 | if (!vfio_find_vpfn(dma, iova)) { | 425 | if (!rsvd && !vfio_find_vpfn(dma, iova)) { |
| 434 | if (!lock_cap && current->mm->locked_vm + 1 > limit) { | 426 | if (!lock_cap && current->mm->locked_vm + 1 > limit) { |
| 435 | put_pfn(*pfn_base, dma->prot); | 427 | put_pfn(*pfn_base, dma->prot); |
| 436 | pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", __func__, | 428 | pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", __func__, |
| @@ -450,12 +442,13 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr, | |||
| 450 | if (ret) | 442 | if (ret) |
| 451 | break; | 443 | break; |
| 452 | 444 | ||
| 453 | if (pfn != *pfn_base + pinned) { | 445 | if (pfn != *pfn_base + pinned || |
| 446 | rsvd != is_invalid_reserved_pfn(pfn)) { | ||
| 454 | put_pfn(pfn, dma->prot); | 447 | put_pfn(pfn, dma->prot); |
| 455 | break; | 448 | break; |
| 456 | } | 449 | } |
| 457 | 450 | ||
| 458 | if (!vfio_find_vpfn(dma, iova)) { | 451 | if (!rsvd && !vfio_find_vpfn(dma, iova)) { |
| 459 | if (!lock_cap && | 452 | if (!lock_cap && |
| 460 | current->mm->locked_vm + lock_acct + 1 > limit) { | 453 | current->mm->locked_vm + lock_acct + 1 > limit) { |
| 461 | put_pfn(pfn, dma->prot); | 454 | put_pfn(pfn, dma->prot); |
| @@ -473,8 +466,10 @@ out: | |||
| 473 | 466 | ||
| 474 | unpin_out: | 467 | unpin_out: |
| 475 | if (ret) { | 468 | if (ret) { |
| 476 | for (pfn = *pfn_base ; pinned ; pfn++, pinned--) | 469 | if (!rsvd) { |
| 477 | put_pfn(pfn, dma->prot); | 470 | for (pfn = *pfn_base ; pinned ; pfn++, pinned--) |
| 471 | put_pfn(pfn, dma->prot); | ||
| 472 | } | ||
| 478 | 473 | ||
| 479 | return ret; | 474 | return ret; |
| 480 | } | 475 | } |
