[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC v4 25/27] vfio-pci: register handler for iommu fault
From: |
Eric Auger |
Subject: |
[Qemu-devel] [RFC v4 25/27] vfio-pci: register handler for iommu fault |
Date: |
Mon, 27 May 2019 13:42:01 +0200 |
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.
As this is the first use of this new IRQ index, also handle it
in irq_to_str() in case the signaling setup fails.
The actual handler will be implemented in subsequent patches.
Signed-off-by: Eric Auger <address@hidden>
---
v3 -> v4:
- check VFIO_PCI_DMA_FAULT_IRQ_INDEX is supported at kernel level
before attempting to set signaling for it.
---
hw/vfio/common.c | 3 +++
hw/vfio/pci.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
hw/vfio/pci.h | 1 +
3 files changed, 56 insertions(+)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 532ede0e70..cf0087321e 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -130,6 +130,9 @@ static char *irq_to_str(int index, int subindex)
case VFIO_PCI_REQ_IRQ_INDEX:
str = g_strdup_printf("REQ-%d", subindex);
break;
+ case VFIO_PCI_DMA_FAULT_IRQ_INDEX:
+ str = g_strdup_printf("DMA-FAULT-%d", subindex);
+ break;
default:
str = g_strdup_printf("index %d (unknown)", index);
break;
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index b613b20501..29d4f633b0 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2736,6 +2736,56 @@ 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)
+{
+ struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info),
+ .index = VFIO_PCI_DMA_FAULT_IRQ_INDEX };
+ Error *err = NULL;
+ int32_t fd;
+
+ if (ioctl(vdev->vbasedev.fd,
+ VFIO_DEVICE_GET_IRQ_INFO, &irq_info) < 0 || irq_info.count < 1) {
+ return;
+ }
+
+ 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);
@@ -3035,6 +3085,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;
@@ -3073,6 +3124,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) {
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index cfcd1a81b8..96d29d667b 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -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;
--
2.20.1
- [Qemu-devel] [RFC v4 16/27] hw/arm/smmuv3: Notify on config changes, (continued)
- [Qemu-devel] [RFC v4 16/27] hw/arm/smmuv3: Notify on config changes, Eric Auger, 2019/05/27
- [Qemu-devel] [RFC v4 17/27] hw/vfio/common: Introduce vfio_alloc_guest_iommu helper, Eric Auger, 2019/05/27
- [Qemu-devel] [RFC v4 18/27] hw/vfio/common: Introduce hostwin_from_range helper, Eric Auger, 2019/05/27
- [Qemu-devel] [RFC v4 19/27] hw/vfio/common: Introduce helpers to DMA map/unmap a RAM section, Eric Auger, 2019/05/27
- [Qemu-devel] [RFC v4 20/27] hw/vfio/common: Setup nested stage mappings, Eric Auger, 2019/05/27
- [Qemu-devel] [RFC v4 21/27] hw/vfio/common: Register a MAP notifier for MSI binding, Eric Auger, 2019/05/27
- [Qemu-devel] [RFC v4 22/27] vfio-pci: Expose MSI stage 1 bindings to the host, Eric Auger, 2019/05/27
- [Qemu-devel] [RFC v4 23/27] memory: Introduce IOMMU Memory Region inject_faults API, Eric Auger, 2019/05/27
- [Qemu-devel] [RFC v4 26/27] vfio-pci: Set up fault regions, Eric Auger, 2019/05/27
- [Qemu-devel] [RFC v4 27/27] vfio-pci: Implement the DMA fault handler, Eric Auger, 2019/05/27
- [Qemu-devel] [RFC v4 25/27] vfio-pci: register handler for iommu fault,
Eric Auger <=
- [Qemu-devel] [RFC v4 24/27] hw/arm/smmuv3: Implement fault injection, Eric Auger, 2019/05/27
- Re: [Qemu-devel] [RFC v4 00/27] vSMMUv3/pSMMUv3 2 stage VFIO integration, no-reply, 2019/05/27