[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC v3 21/27] hw/vfio/common: Register a MAP notifier for
From: |
Eric Auger |
Subject: |
[Qemu-devel] [RFC v3 21/27] hw/vfio/common: Register a MAP notifier for MSI binding |
Date: |
Fri, 12 Apr 2019 12:03:48 +0200 |
Instantiate a MAP notifier to register the MSI stage 1
binding (gIOVA -> gDB) to the host. This allows the host
to build a nested mapping towards the physical doorbell:
guest IOVA -> guest Doorbell -> physical doorbell.
Stage1 Stage 2
The unregistration is done on VFIO container deallocation.
Signed-off-by: Eric Auger <address@hidden>
---
v2 -> v3:
- only register the notifier if the IOMMU translates MSIs
- record the msi bindings in a container list and unregister on
container release
---
hw/vfio/common.c | 69 +++++++++++++++++++++++++++++++++++
include/hw/vfio/vfio-common.h | 8 ++++
2 files changed, 77 insertions(+)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index e9b729a503..051be723fd 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -489,6 +489,56 @@ static void vfio_iommu_unmap_notify(IOMMUNotifier *n,
IOMMUTLBEntry *iotlb)
}
}
+static void vfio_iommu_msi_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
+{
+ VFIOGuestIOMMU *giommu = container_of(n, VFIOGuestIOMMU, n);
+ VFIOContainer *container = giommu->container;
+ int ret;
+
+ struct vfio_iommu_type1_bind_msi ustruct;
+ VFIOMSIBinding *binding;
+
+ QLIST_FOREACH(binding, &container->msibinding_list, next) {
+ if (binding->iova == iotlb->iova) {
+ return;
+ }
+ }
+ ustruct.argsz = sizeof(struct vfio_iommu_type1_bind_msi);
+ ustruct.flags = 0;
+
+ ustruct.iova = iotlb->iova;
+ ustruct.gpa = iotlb->translated_addr;
+ ustruct.size = iotlb->addr_mask + 1;
+ ret = ioctl(container->fd, VFIO_IOMMU_BIND_MSI , &ustruct);
+ if (ret) {
+ error_report("%s: failed to register the stage1 MSI binding (%d)",
+ __func__, ret);
+ }
+ binding = g_new0(VFIOMSIBinding, 1);
+ binding->iova = ustruct.iova;
+ binding->gpa = ustruct.gpa;
+ binding->size = ustruct.size;
+
+ QLIST_INSERT_HEAD(&container->msibinding_list, binding, next);
+}
+
+static void vfio_container_unbind_msis(VFIOContainer *container)
+{
+ VFIOMSIBinding *binding, *tmp;
+
+ QLIST_FOREACH_SAFE(binding, &container->msibinding_list, next, tmp) {
+ struct vfio_iommu_type1_unbind_msi ustruct;
+
+ /* the MSI doorbell is not used anymore, unregister it */
+ ustruct.argsz = sizeof(struct vfio_iommu_type1_unbind_msi);
+ ustruct.flags = 0;
+ ustruct.iova = binding->iova;
+ ioctl(container->fd, VFIO_IOMMU_UNBIND_MSI , &ustruct);
+ QLIST_REMOVE(binding, next);
+ g_free(binding);
+ }
+}
+
static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
{
VFIOGuestIOMMU *giommu = container_of(n, VFIOGuestIOMMU, n);
@@ -816,6 +866,8 @@ static void vfio_listener_region_add(MemoryListener
*listener,
MEMTXATTRS_UNSPECIFIED);
if (container->iommu_type == VFIO_TYPE1_NESTING_IOMMU) {
+ bool translate_msi;
+
/* Config notifier to propagate guest stage 1 config changes */
giommu = vfio_alloc_guest_iommu(container, iommu_mr, offset);
iommu_config_notifier_init(&giommu->n, vfio_iommu_nested_notify,
@@ -832,6 +884,21 @@ static void vfio_listener_region_add(MemoryListener
*listener,
iommu_idx);
QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);
memory_region_register_iommu_notifier(section->mr, &giommu->n);
+
+ memory_region_iommu_get_attr(iommu_mr, IOMMU_ATTR_MSI_TRANSLATE,
+ (void *)&translate_msi);
+ if (translate_msi) {
+ giommu = vfio_alloc_guest_iommu(container, iommu_mr, offset);
+ iommu_iotlb_notifier_init(&giommu->n,
+ vfio_iommu_msi_map_notify,
+ IOMMU_NOTIFIER_IOTLB_MAP,
+ section->offset_within_region,
+ int128_get64(llend),
+ iommu_idx);
+ QLIST_INSERT_HEAD(&container->giommu_list, giommu,
+ giommu_next);
+ memory_region_register_iommu_notifier(section->mr, &giommu->n);
+ }
} else {
/* MAP/UNMAP IOTLB notifier */
giommu = vfio_alloc_guest_iommu(container, iommu_mr, offset);
@@ -1608,6 +1675,8 @@ static void vfio_disconnect_container(VFIOGroup *group)
g_free(giommu);
}
+ vfio_container_unbind_msis(container);
+
trace_vfio_disconnect_container(container->fd);
close(container->fd);
g_free(container);
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index 686d99ff8c..c862d87725 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -64,6 +64,13 @@ typedef struct VFIOAddressSpace {
QLIST_ENTRY(VFIOAddressSpace) list;
} VFIOAddressSpace;
+typedef struct VFIOMSIBinding {
+ hwaddr iova;
+ hwaddr gpa;
+ hwaddr size;
+ QLIST_ENTRY(VFIOMSIBinding) next;
+} VFIOMSIBinding;
+
struct VFIOGroup;
typedef struct VFIOContainer {
@@ -83,6 +90,7 @@ typedef struct VFIOContainer {
QLIST_HEAD(, VFIOGuestIOMMU) giommu_list;
QLIST_HEAD(, VFIOHostDMAWindow) hostwin_list;
QLIST_HEAD(, VFIOGroup) group_list;
+ QLIST_HEAD(, VFIOMSIBinding) msibinding_list;
QLIST_ENTRY(VFIOContainer) next;
} VFIOContainer;
--
2.20.1
- [Qemu-devel] [RFC v3 12/27] hw/arm/smmuv3: Store the PASID table GPA in the translation config, (continued)
- [Qemu-devel] [RFC v3 12/27] hw/arm/smmuv3: Store the PASID table GPA in the translation config, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 11/27] memory: Add arch_id and leaf fields in IOTLBEntry, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 13/27] hw/arm/smmuv3: Implement dummy replay, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 14/27] hw/arm/smmuv3: Fill the IOTLBEntry arch_id on NH_VA invalidation, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 15/27] hw/arm/smmuv3: Fill the IOTLBEntry leaf field on NH_VA invalidation, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 16/27] hw/arm/smmuv3: Notify on config changes, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 17/27] hw/vfio/common: Introduce vfio_alloc_guest_iommu helper, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 18/27] hw/vfio/common: Introduce hostwin_from_range helper, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 19/27] hw/vfio/common: Introduce helpers to DMA map/unap a RAM section, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 20/27] hw/vfio/common: Setup nested stage mappings, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 21/27] hw/vfio/common: Register a MAP notifier for MSI binding,
Eric Auger <=
- [Qemu-devel] [RFC v3 22/27] vfio-pci: Expose MSI stage 1 bindings to the host, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 23/27] memory: Introduce IOMMU Memory Region inject_faults API, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 24/27] hw/arm/smmuv3: Implement fault injection, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 25/27] vfio-pci: register handler for iommu fault, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 26/27] vfio-pci: Set up fault regions, Eric Auger, 2019/04/12
- [Qemu-devel] [RFC v3 27/27] vfio-pci: Implement the DMA fault handler, Eric Auger, 2019/04/12
- Re: [Qemu-devel] [RFC v3 00/27] vSMMUv3/pSMMUv3 2 stage VFIO integration, no-reply, 2019/04/12