@@ -2722,6 +2722,49 @@ static void vfio_unregister_req_notifier(VFIOPCIDevice *vdev)
vdev->req_enabled = false;
}
+static void vfio_dma_fault_notifier_handler(void *opaque)
+{
+ VFIOPCIDevice *vdev = opaque;
+
+ if (!event_notifier_test_and_clear(&vdev->dma_fault_notifier)) {
+ return;
+ }
+}
+
+static void vfio_register_dma_fault_notifier(VFIOPCIDevice *vdev)
+{
+ Error *err = NULL;
+ int32_t fd;
+
+ if (event_notifier_init(&vdev->dma_fault_notifier, 0)) {
+ error_report("vfio: Unable to init event notifier for dma fault");
+ return;
+ }
+
+ fd = event_notifier_get_fd(&vdev->dma_fault_notifier);
+ qemu_set_fd_handler(fd, vfio_dma_fault_notifier_handler, NULL, vdev);
+
+ if (vfio_set_irq_signaling(&vdev->vbasedev, VFIO_PCI_DMA_FAULT_IRQ_INDEX, 0,
+ VFIO_IRQ_SET_ACTION_TRIGGER, fd, &err)) {
+ error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
+ qemu_set_fd_handler(fd, NULL, NULL, vdev);
+ event_notifier_cleanup(&vdev->dma_fault_notifier);
+ }
+}
+
+static void vfio_unregister_dma_fault_notifier(VFIOPCIDevice *vdev)
+{
+ Error *err = NULL;
+
+ if (vfio_set_irq_signaling(&vdev->vbasedev, VFIO_PCI_DMA_FAULT_IRQ_INDEX, 0,
+ VFIO_IRQ_SET_ACTION_TRIGGER, -1, &err)) {
+ error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
+ }
+ qemu_set_fd_handler(event_notifier_get_fd(&vdev->dma_fault_notifier),
+ NULL, NULL, vdev);
+ event_notifier_cleanup(&vdev->dma_fault_notifier);
+}
+
static void vfio_realize(PCIDevice *pdev, Error **errp)
{
VFIOPCIDevice *vdev = PCI_VFIO(pdev);
@@ -3007,6 +3050,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
vfio_register_err_notifier(vdev);
vfio_register_req_notifier(vdev);
+ vfio_register_dma_fault_notifier(vdev);
vfio_setup_resetfn_quirk(vdev);
return;
@@ -3045,6 +3089,7 @@ static void vfio_exitfn(PCIDevice *pdev)
vfio_unregister_req_notifier(vdev);
vfio_unregister_err_notifier(vdev);
+ vfio_unregister_dma_fault_notifier(vdev);
pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
vfio_disable_interrupts(vdev);
if (vdev->intx.mmap_timer) {
@@ -135,6 +135,7 @@ typedef struct VFIOPCIDevice {
PCIHostDeviceAddress host;
EventNotifier err_notifier;
EventNotifier req_notifier;
+ EventNotifier dma_fault_notifier;
int (*resetfn)(struct VFIOPCIDevice *);
uint32_t vendor_id;
uint32_t device_id;
We use the VFIO_PCI_DMA_FAULT_IRQ_INDEX "irq" index to set/unset a notifier for physical DMA faults. The associated eventfd is triggered, in nested mode, whenever a fault is detected at IOMMU physical level. The actual handler will be implemented in subsequent patches. Signed-off-by: Eric Auger <eric.auger@redhat.com> --- --- hw/vfio/pci.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ hw/vfio/pci.h | 1 + 2 files changed, 46 insertions(+)