All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Auger <eric.auger@redhat.com>
To: eric.auger.pro@gmail.com, eric.auger@redhat.com,
	qemu-devel@nongnu.org, qemu-arm@nongnu.org,
	peter.maydell@linaro.org
Cc: alex.williamson@redhat.com, mst@redhat.com,
	jean-philippe.brucker@arm.com, peterx@redhat.com,
	yi.l.liu@intel.com, vincent.stehle@arm.com
Subject: [Qemu-devel] [RFC v3 22/27] vfio-pci: Expose MSI stage 1 bindings to the host
Date: Fri, 12 Apr 2019 12:03:49 +0200	[thread overview]
Message-ID: <20190412100354.6409-23-eric.auger@redhat.com> (raw)
In-Reply-To: <20190412100354.6409-1-eric.auger@redhat.com>

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 <eric.auger@redhat.com>
---
 hw/arm/smmuv3.c      |  8 --------
 hw/vfio/pci.c        | 48 ++++++++++++++++++++++++++++++++++++++++++++
 hw/vfio/trace-events |  2 ++
 3 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 2574989f2e..a7e48e7972 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -1517,14 +1517,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 cd93ff6fa3..aeb4dfa388 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -402,6 +402,48 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix)
     return ret;
 }
 
+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 void vfio_add_kvm_msi_virq(VFIOPCIDevice *vdev, VFIOMSIVector *vector,
                                   int vector_n, bool msix)
 {
@@ -487,6 +529,12 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
         }
     }
 
+    ret = vfio_register_msi_binding(vdev, nr);
+
+    if (ret) {
+        error_report("%s failed to register S1 MSI binding(%d)", __func__, ret);
+    }
+
     /*
      * We don't want to have the host allocate all possible MSI vectors
      * for a device if they're not in use, so we shutdown and incrementally
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index 3c2cd15e3f..52b96ec196 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -111,6 +111,8 @@ vfio_region_sparse_mmap_header(const char *name, int index, int nr_areas) "Devic
 vfio_region_sparse_mmap_entry(int i, unsigned long start, unsigned long end) "sparse entry %d [0x%lx - 0x%lx]"
 vfio_get_dev_region(const char *name, int index, uint32_t type, uint32_t subtype) "%s index %d, %08x/%0x8"
 vfio_dma_unmap_overflow_workaround(void) ""
+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

WARNING: multiple messages have this Message-ID (diff)
From: Eric Auger <eric.auger@redhat.com>
To: eric.auger.pro@gmail.com, eric.auger@redhat.com,
	qemu-devel@nongnu.org, qemu-arm@nongnu.org,
	peter.maydell@linaro.org
Cc: yi.l.liu@intel.com, mst@redhat.com,
	jean-philippe.brucker@arm.com, peterx@redhat.com,
	alex.williamson@redhat.com, vincent.stehle@arm.com
Subject: [Qemu-devel] [RFC v3 22/27] vfio-pci: Expose MSI stage 1 bindings to the host
Date: Fri, 12 Apr 2019 12:03:49 +0200	[thread overview]
Message-ID: <20190412100354.6409-23-eric.auger@redhat.com> (raw)
Message-ID: <20190412100349.FPKuy4Ti31vPHeAHXIxQhPxrXGvlgQlehvs_lg5qIeM@z> (raw)
In-Reply-To: <20190412100354.6409-1-eric.auger@redhat.com>

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 <eric.auger@redhat.com>
---
 hw/arm/smmuv3.c      |  8 --------
 hw/vfio/pci.c        | 48 ++++++++++++++++++++++++++++++++++++++++++++
 hw/vfio/trace-events |  2 ++
 3 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 2574989f2e..a7e48e7972 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -1517,14 +1517,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 cd93ff6fa3..aeb4dfa388 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -402,6 +402,48 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix)
     return ret;
 }
 
+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 void vfio_add_kvm_msi_virq(VFIOPCIDevice *vdev, VFIOMSIVector *vector,
                                   int vector_n, bool msix)
 {
@@ -487,6 +529,12 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
         }
     }
 
+    ret = vfio_register_msi_binding(vdev, nr);
+
+    if (ret) {
+        error_report("%s failed to register S1 MSI binding(%d)", __func__, ret);
+    }
+
     /*
      * We don't want to have the host allocate all possible MSI vectors
      * for a device if they're not in use, so we shutdown and incrementally
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index 3c2cd15e3f..52b96ec196 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -111,6 +111,8 @@ vfio_region_sparse_mmap_header(const char *name, int index, int nr_areas) "Devic
 vfio_region_sparse_mmap_entry(int i, unsigned long start, unsigned long end) "sparse entry %d [0x%lx - 0x%lx]"
 vfio_get_dev_region(const char *name, int index, uint32_t type, uint32_t subtype) "%s index %d, %08x/%0x8"
 vfio_dma_unmap_overflow_workaround(void) ""
+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



  parent reply	other threads:[~2019-04-12 10:06 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-12 10:03 [Qemu-devel] [RFC v3 00/27] vSMMUv3/pSMMUv3 2 stage VFIO integration Eric Auger
2019-04-12 10:03 ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 01/27] hw/arm/smmuv3: Remove SMMUNotifierNode Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 02/27] vfio/common: Introduce vfio_set_irq_signaling helper Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 03/27] update-linux-headers: Import iommu.h Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 04/27] header update against 5.1-rc3 and IOMMU/VFIO nested stage APIs Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 05/27] memory: add IOMMU_ATTR_VFIO_NESTED IOMMU memory region attribute Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 06/27] memory: add IOMMU_ATTR_MSI_TRANSLATE " Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 07/27] hw/arm/smmuv3: Advertise VFIO_NESTED and MSI_TRANSLATE attributes Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 08/27] hw/vfio/common: Force nested if iommu requires it Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 09/27] memory: Prepare for different kinds of IOMMU MR notifiers Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 10/27] memory: Add IOMMUConfigNotifier Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 11/27] memory: Add arch_id and leaf fields in IOTLBEntry Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 12/27] hw/arm/smmuv3: Store the PASID table GPA in the translation config Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 13/27] hw/arm/smmuv3: Implement dummy replay Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 14/27] hw/arm/smmuv3: Fill the IOTLBEntry arch_id on NH_VA invalidation Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 15/27] hw/arm/smmuv3: Fill the IOTLBEntry leaf field " Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 16/27] hw/arm/smmuv3: Notify on config changes Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 17/27] hw/vfio/common: Introduce vfio_alloc_guest_iommu helper Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 18/27] hw/vfio/common: Introduce hostwin_from_range helper Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 19/27] hw/vfio/common: Introduce helpers to DMA map/unap a RAM section Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 20/27] hw/vfio/common: Setup nested stage mappings Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 21/27] hw/vfio/common: Register a MAP notifier for MSI binding Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` Eric Auger [this message]
2019-04-12 10:03   ` [Qemu-devel] [RFC v3 22/27] vfio-pci: Expose MSI stage 1 bindings to the host Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 23/27] memory: Introduce IOMMU Memory Region inject_faults API Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 24/27] hw/arm/smmuv3: Implement fault injection Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 25/27] vfio-pci: register handler for iommu fault Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 26/27] vfio-pci: Set up fault regions Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:03 ` [Qemu-devel] [RFC v3 27/27] vfio-pci: Implement the DMA fault handler Eric Auger
2019-04-12 10:03   ` Eric Auger
2019-04-12 10:46 ` [Qemu-devel] [RFC v3 00/27] vSMMUv3/pSMMUv3 2 stage VFIO integration no-reply
2019-04-12 10:46   ` no-reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190412100354.6409-23-eric.auger@redhat.com \
    --to=eric.auger@redhat.com \
    --cc=alex.williamson@redhat.com \
    --cc=eric.auger.pro@gmail.com \
    --cc=jean-philippe.brucker@arm.com \
    --cc=mst@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=peterx@redhat.com \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=vincent.stehle@arm.com \
    --cc=yi.l.liu@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.