Skip to content

Commit d71a989

Browse files
committed
vfio/pci: Insert full vma on mmap'd MMIO fault
In order to improve performance of typical scenarios we can try to insert the entire vma on fault. This accelerates typical cases, such as when the MMIO region is DMA mapped by QEMU. The vfio_iommu_type1 driver will fault in the entire DMA mapped range through fixup_user_fault(). In synthetic testing, this improves the time required to walk a PCI BAR mapping from userspace by roughly 1/3rd. This is likely an interim solution until vmf_insert_pfn_{pmd,pud}() gain support for pfnmaps. Suggested-by: Yan Zhao <yan.y.zhao@intel.com> Link: https://lore.kernel.org/all/Zl6XdUkt%2FzMMGOLF@yzhao56-desk.sh.intel.com/ Reviewed-by: Yan Zhao <yan.y.zhao@intel.com> Link: https://lore.kernel.org/r/20240607035213.2054226-1-alex.williamson@redhat.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
1 parent aac6db7 commit d71a989

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

drivers/vfio/pci/vfio_pci_core.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,18 +1662,33 @@ static vm_fault_t vfio_pci_mmap_fault(struct vm_fault *vmf)
16621662
struct vm_area_struct *vma = vmf->vma;
16631663
struct vfio_pci_core_device *vdev = vma->vm_private_data;
16641664
unsigned long pfn, pgoff = vmf->pgoff - vma->vm_pgoff;
1665+
unsigned long addr = vma->vm_start;
16651666
vm_fault_t ret = VM_FAULT_SIGBUS;
16661667

16671668
pfn = vma_to_pfn(vma);
16681669

16691670
down_read(&vdev->memory_lock);
16701671

16711672
if (vdev->pm_runtime_engaged || !__vfio_pci_memory_enabled(vdev))
1672-
goto out_disabled;
1673+
goto out_unlock;
16731674

16741675
ret = vmf_insert_pfn(vma, vmf->address, pfn + pgoff);
1676+
if (ret & VM_FAULT_ERROR)
1677+
goto out_unlock;
16751678

1676-
out_disabled:
1679+
/*
1680+
* Pre-fault the remainder of the vma, abort further insertions and
1681+
* supress error if fault is encountered during pre-fault.
1682+
*/
1683+
for (; addr < vma->vm_end; addr += PAGE_SIZE, pfn++) {
1684+
if (addr == vmf->address)
1685+
continue;
1686+
1687+
if (vmf_insert_pfn(vma, addr, pfn) & VM_FAULT_ERROR)
1688+
break;
1689+
}
1690+
1691+
out_unlock:
16771692
up_read(&vdev->memory_lock);
16781693

16791694
return ret;

0 commit comments

Comments
 (0)