Skip to content

Commit c1d9dac

Browse files
committed
vfio/pci: Align huge faults to order
The vfio-pci huge_fault handler doesn't make any attempt to insert a mapping containing the faulting address, it only inserts mappings if the faulting address and resulting pfn are aligned. This works in a lot of cases, particularly in conjunction with QEMU where DMA mappings linearly fault the mmap. However, there are configurations where we don't get that linear faulting and pages are faulted on-demand. The scenario reported in the bug below is such a case, where the physical address width of the CPU is greater than that of the IOMMU, resulting in a VM where guest firmware has mapped device MMIO beyond the address width of the IOMMU. In this configuration, the MMIO is faulted on demand and tracing indicates that occasionally the faults generate a VM_FAULT_OOM. Given the use case, this results in a "error: kvm run failed Bad address", killing the VM. The host is not under memory pressure in this test, therefore it's suspected that VM_FAULT_OOM is actually the result of a NULL return from __pte_offset_map_lock() in the get_locked_pte() path from insert_pfn(). This suggests a potential race inserting a pte concurrent to a pmd, and maybe indicates some deficiency in the mm layer properly handling such a case. Nevertheless, Peter noted the inconsistency of vfio-pci's huge_fault handler where our mapping granularity depends on the alignment of the faulting address relative to the order rather than aligning the faulting address to the order to more consistently insert huge mappings. This change not only uses the page tables more consistently and efficiently, but as any fault to an aligned page results in the same mapping, the race condition suspected in the VM_FAULT_OOM is avoided. Reported-by: Adolfo <adolfotregosa@gmail.com> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220057 Fixes: 09dfc8a ("vfio/pci: Fallback huge faults for unaligned pfn") Cc: stable@vger.kernel.org Tested-by: Adolfo <adolfotregosa@gmail.com> Co-developed-by: Peter Xu <peterx@redhat.com> Signed-off-by: Peter Xu <peterx@redhat.com> Link: https://lore.kernel.org/r/20250502224035.3183451-1-alex.williamson@redhat.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
1 parent 92a09c4 commit c1d9dac

File tree

1 file changed

+6
-6
lines changed

1 file changed

+6
-6
lines changed

drivers/vfio/pci/vfio_pci_core.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,14 +1646,14 @@ static vm_fault_t vfio_pci_mmap_huge_fault(struct vm_fault *vmf,
16461646
{
16471647
struct vm_area_struct *vma = vmf->vma;
16481648
struct vfio_pci_core_device *vdev = vma->vm_private_data;
1649-
unsigned long pfn, pgoff = vmf->pgoff - vma->vm_pgoff;
1649+
unsigned long addr = vmf->address & ~((PAGE_SIZE << order) - 1);
1650+
unsigned long pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
1651+
unsigned long pfn = vma_to_pfn(vma) + pgoff;
16501652
vm_fault_t ret = VM_FAULT_SIGBUS;
16511653

1652-
pfn = vma_to_pfn(vma) + pgoff;
1653-
1654-
if (order && (pfn & ((1 << order) - 1) ||
1655-
vmf->address & ((PAGE_SIZE << order) - 1) ||
1656-
vmf->address + (PAGE_SIZE << order) > vma->vm_end)) {
1654+
if (order && (addr < vma->vm_start ||
1655+
addr + (PAGE_SIZE << order) > vma->vm_end ||
1656+
pfn & ((1 << order) - 1))) {
16571657
ret = VM_FAULT_FALLBACK;
16581658
goto out;
16591659
}

0 commit comments

Comments
 (0)