diff --git a/vfio-pci-Implement-the-DMA-fault-handler.patch b/vfio-pci-Implement-the-DMA-fault-handler.patch new file mode 100644 index 0000000..ca61b01 --- /dev/null +++ b/vfio-pci-Implement-the-DMA-fault-handler.patch @@ -0,0 +1,96 @@ +From 139d0b3474c29427fea4a0ed47f51c01a76a8636 Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Tue, 5 Mar 2019 16:35:32 +0100 +Subject: [PATCH] vfio/pci: Implement the DMA fault handler + +Whenever the eventfd is triggered, we retrieve the DMA fault(s) +from the mmapped fault region and inject them in the iommu +memory region. + +Signed-off-by: Eric Auger +Signed-off-by: Kunkun Jiang +--- + hw/vfio/pci.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ + hw/vfio/pci.h | 1 + + 2 files changed, 51 insertions(+) + +diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c +index 0db7d68258..d1198c8a23 100644 +--- a/hw/vfio/pci.c ++++ b/hw/vfio/pci.c +@@ -2922,10 +2922,60 @@ static PCIPASIDOps vfio_pci_pasid_ops = { + static void vfio_dma_fault_notifier_handler(void *opaque) + { + VFIOPCIExtIRQ *ext_irq = opaque; ++ VFIOPCIDevice *vdev = ext_irq->vdev; ++ PCIDevice *pdev = &vdev->pdev; ++ AddressSpace *as = pci_device_iommu_address_space(pdev); ++ IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(as->root); ++ struct vfio_region_dma_fault header; ++ struct iommu_fault *queue; ++ char *queue_buffer = NULL; ++ ssize_t bytes; + + if (!event_notifier_test_and_clear(&ext_irq->notifier)) { + return; + } ++ ++ bytes = pread(vdev->vbasedev.fd, &header, sizeof(header), ++ vdev->dma_fault_region.fd_offset); ++ if (bytes != sizeof(header)) { ++ error_report("%s unable to read the fault region header (0x%lx)", ++ __func__, bytes); ++ return; ++ } ++ ++ /* Normally the fault queue is mmapped */ ++ queue = (struct iommu_fault *)vdev->dma_fault_region.mmaps[0].mmap; ++ if (!queue) { ++ size_t queue_size = header.nb_entries * header.entry_size; ++ ++ error_report("%s: fault queue not mmapped: slower fault handling", ++ vdev->vbasedev.name); ++ ++ queue_buffer = g_malloc(queue_size); ++ bytes = pread(vdev->vbasedev.fd, queue_buffer, queue_size, ++ vdev->dma_fault_region.fd_offset + header.offset); ++ if (bytes != queue_size) { ++ error_report("%s unable to read the fault queue (0x%lx)", ++ __func__, bytes); ++ return; ++ } ++ ++ queue = (struct iommu_fault *)queue_buffer; ++ } ++ ++ while (vdev->fault_tail_index != header.head) { ++ memory_region_inject_faults(iommu_mr, 1, ++ &queue[vdev->fault_tail_index]); ++ vdev->fault_tail_index = ++ (vdev->fault_tail_index + 1) % header.nb_entries; ++ } ++ bytes = pwrite(vdev->vbasedev.fd, &vdev->fault_tail_index, 4, ++ vdev->dma_fault_region.fd_offset); ++ if (bytes != 4) { ++ error_report("%s unable to write the fault region tail index (0x%lx)", ++ __func__, bytes); ++ } ++ g_free(queue_buffer); + } + + static int vfio_register_ext_irq_handler(VFIOPCIDevice *vdev, +diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h +index 815154656c..e31bc0173a 100644 +--- a/hw/vfio/pci.h ++++ b/hw/vfio/pci.h +@@ -142,6 +142,7 @@ typedef struct VFIOPCIDevice { + EventNotifier req_notifier; + VFIOPCIExtIRQ *ext_irqs; + VFIORegion dma_fault_region; ++ uint32_t fault_tail_index; + int (*resetfn)(struct VFIOPCIDevice *); + uint32_t vendor_id; + uint32_t device_id; +-- +2.27.0 +