[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-arm] [RFC v4 22/27] vfio-pci: Expose MSI stage 1 bindings to the h
From: |
Eric Auger |
Subject: |
[Qemu-arm] [RFC v4 22/27] vfio-pci: Expose MSI stage 1 bindings to the host |
Date: |
Mon, 27 May 2019 13:41:58 +0200 |
When the guest is exposed with a virtual IOMMU that translates
MSIs, the guest allocates an IOVA (gIOVA) that maps the virtual
doorbell (gDB). In nested mode, when the MSI is setup, we pass
this stage1 mapping to the host so that it can use this stage1
binding to create a nested stage translating into the physical
doorbell. Conversely, when the MSI setup os torn down, we
unregister this binding.
For registration, We directly use the iommu memory region
translate() callback since the addr_mask is returned in the
IOTLB entry. address_space_translate does not return this information.
Now that we use a MAP notifier, let's remove warning against
the usage of map notifiers (historically used along with Intel's
caching mode).
Signed-off-by: Eric Auger <address@hidden>
---
v3 -> v4:
- move the MSI binding registration in vfio_enable_vectors
to address the MSI use case
---
hw/arm/smmuv3.c | 8 -------
hw/vfio/pci.c | 50 +++++++++++++++++++++++++++++++++++++++++++-
hw/vfio/trace-events | 2 ++
3 files changed, 51 insertions(+), 9 deletions(-)
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index db03313672..a697968ace 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -1521,14 +1521,6 @@ static void smmuv3_notify_flag_changed(IOMMUMemoryRegion
*iommu,
SMMUv3State *s3 = sdev->smmu;
SMMUState *s = &(s3->smmu_state);
- if (new & IOMMU_NOTIFIER_IOTLB_MAP) {
- int bus_num = pci_bus_num(sdev->bus);
- PCIDevice *pcidev = pci_find_device(sdev->bus, bus_num, sdev->devfn);
-
- warn_report("SMMUv3 does not support notification on MAP: "
- "device %s will not function properly", pcidev->name);
- }
-
if (old == IOMMU_NOTIFIER_NONE) {
trace_smmuv3_notify_flag_add(iommu->parent_obj.name);
QLIST_INSERT_HEAD(&s->devices_with_notifiers, sdev, next);
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 3095379747..b613b20501 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -358,6 +358,48 @@ static void vfio_msi_interrupt(void *opaque)
notify(&vdev->pdev, nr);
}
+static int vfio_register_msi_binding(VFIOPCIDevice *vdev, int vector_n)
+{
+ PCIDevice *dev = &vdev->pdev;
+ AddressSpace *as = pci_device_iommu_address_space(dev);
+ MSIMessage msg = pci_get_msi_message(dev, vector_n);
+ IOMMUMemoryRegionClass *imrc;
+ IOMMUMemoryRegion *iommu_mr;
+ bool msi_translate = false, nested = false;;
+ IOMMUTLBEntry entry;
+
+ if (as == &address_space_memory) {
+ return 0;
+ }
+
+ iommu_mr = IOMMU_MEMORY_REGION(as->root);
+ memory_region_iommu_get_attr(iommu_mr, IOMMU_ATTR_MSI_TRANSLATE,
+ (void *)&msi_translate);
+ memory_region_iommu_get_attr(iommu_mr, IOMMU_ATTR_VFIO_NESTED,
+ (void *)&nested);
+ imrc = memory_region_get_iommu_class_nocheck(iommu_mr);
+
+ if (!nested || !msi_translate) {
+ return 0;
+ }
+
+ /* MSI doorbell address is translated by an IOMMU */
+
+ rcu_read_lock();
+ entry = imrc->translate(iommu_mr, msg.address, IOMMU_WO, 0);
+ rcu_read_unlock();
+
+ if (entry.perm == IOMMU_NONE) {
+ return -ENOENT;
+ }
+
+ trace_vfio_register_msi_binding(vdev->vbasedev.name, vector_n,
+ msg.address, entry.translated_addr);
+
+ memory_region_iotlb_notify_iommu(iommu_mr, 0, entry);
+ return 0;
+}
+
static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix)
{
struct vfio_irq_set *irq_set;
@@ -375,7 +417,7 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool
msix)
fds = (int32_t *)&irq_set->data;
for (i = 0; i < vdev->nr_vectors; i++) {
- int fd = -1;
+ int ret, fd = -1;
/*
* MSI vs MSI-X - The guest has direct access to MSI mask and pending
@@ -390,6 +432,12 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool
msix)
} else {
fd =
event_notifier_get_fd(&vdev->msi_vectors[i].kvm_interrupt);
}
+ ret = vfio_register_msi_binding(vdev, i);
+ if (ret) {
+ error_report("%s failed to register S1 MSI binding "
+ "for vector %d(%d)", __func__, i, ret);
+ return ret;
+ }
}
fds[i] = fd;
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index 9f1868af2d..5de97a8882 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -117,6 +117,8 @@ vfio_get_dev_region(const char *name, int index, uint32_t
type, uint32_t subtype
vfio_dma_unmap_overflow_workaround(void) ""
vfio_iommu_addr_inv_iotlb(int asid, uint64_t addr, uint64_t size, uint64_t
nb_granules, bool leaf) "nested IOTLB invalidate asid=%d, addr=0x%"PRIx64"
granule_size=0x%"PRIx64" nb_granules=0x%"PRIx64" leaf=%d"
vfio_iommu_asid_inv_iotlb(int asid) "nested IOTLB invalidate asid=%d"
+vfio_register_msi_binding(const char *name, int vector, uint64_t giova,
uint64_t gdb) "%s: register vector %d gIOVA=0x%"PRIx64 "-> gDB=0x%"PRIx64"
stage 1 mapping"
+vfio_unregister_msi_binding(const char *name, int vector, uint64_t giova) "%s:
unregister vector %d gIOVA=0x%"PRIx64 " stage 1 mapping"
# platform.c
vfio_platform_base_device_init(char *name, int groupid) "%s belongs to group
#%d"
--
2.20.1
- [Qemu-arm] [RFC v4 12/27] hw/arm/smmuv3: Store the PASID table GPA in the translation config, (continued)
- [Qemu-arm] [RFC v4 12/27] hw/arm/smmuv3: Store the PASID table GPA in the translation config, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 13/27] hw/arm/smmuv3: Implement dummy replay, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 14/27] hw/arm/smmuv3: Fill the IOTLBEntry arch_id on NH_VA invalidation, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 15/27] hw/arm/smmuv3: Fill the IOTLBEntry leaf field on NH_VA invalidation, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 16/27] hw/arm/smmuv3: Notify on config changes, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 17/27] hw/vfio/common: Introduce vfio_alloc_guest_iommu helper, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 18/27] hw/vfio/common: Introduce hostwin_from_range helper, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 19/27] hw/vfio/common: Introduce helpers to DMA map/unmap a RAM section, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 20/27] hw/vfio/common: Setup nested stage mappings, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 21/27] hw/vfio/common: Register a MAP notifier for MSI binding, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 22/27] vfio-pci: Expose MSI stage 1 bindings to the host,
Eric Auger <=
- [Qemu-arm] [RFC v4 23/27] memory: Introduce IOMMU Memory Region inject_faults API, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 26/27] vfio-pci: Set up fault regions, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 27/27] vfio-pci: Implement the DMA fault handler, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 24/27] hw/arm/smmuv3: Implement fault injection, Eric Auger, 2019/05/27
- [Qemu-arm] [RFC v4 25/27] vfio-pci: register handler for iommu fault, Eric Auger, 2019/05/27
- Re: [Qemu-arm] [Qemu-devel] [RFC v4 00/27] vSMMUv3/pSMMUv3 2 stage VFIO integration, no-reply, 2019/05/27