diff mbox series

[v2,14/19] util/vfio-helpers: Pass minimum page size to qemu_vfio_open_pci()

Message ID 20201026105504.4023620-15-philmd@redhat.com
State New, archived
Headers show
Series util/vfio-helpers: Allow using multiple MSIX IRQs | expand

Commit Message

Philippe Mathieu-Daudé Oct. 26, 2020, 10:54 a.m. UTC
The block driver asks for a minimum page size, but it might not
match the minimum IOMMU requirement.

In the next commit qemu_vfio_init_pci() will be able to report
the minimum IOMMU page size back to the block driver.
In preparation, pass the minimum page size as argument to
qemu_vfio_open_pci(). Add a check to be sure the IOMMU minimum
page size is in range with our NVMe device maximum page size.

Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 include/qemu/vfio-helpers.h |  3 ++-
 block/nvme.c                | 14 +++++++++++++-
 util/vfio-helpers.c         |  8 +++++++-
 3 files changed, 22 insertions(+), 3 deletions(-)

Comments

Stefan Hajnoczi Oct. 27, 2020, 9:50 a.m. UTC | #1
On Mon, Oct 26, 2020 at 11:54:59AM +0100, Philippe Mathieu-Daudé wrote:
> @@ -737,6 +738,17 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
>      }
>  
>      device_page_size_min = 1u << (12 + NVME_CAP_MPSMIN(cap));
> +    device_page_size_max = 1u << (12 + NVME_CAP_MPSMAX(cap));
> +    if (iommu_page_size_min > device_page_size_max) {
> +        g_autofree char *iommu_page_size_s = size_to_str(iommu_page_size_min);
> +        g_autofree char *device_page_size_s = size_to_str(device_page_size_max);
> +
> +        error_setg(errp, "IOMMU minimum page size (%s)"
> +                         " too big for device (max %s)",
> +                   iommu_page_size_s, device_page_size_s);
> +        ret = -EINVAL;
> +        goto out;
> +    }

I thought you and Eric worked on a solution to support smaller device
pages on bigger IOMMU pages? For example, 4KB device page size on 64KB
IOMMU page size.

Won't this check be removed again very soon? Why add it at all?
diff mbox series

Patch

diff --git a/include/qemu/vfio-helpers.h b/include/qemu/vfio-helpers.h
index bde9495b254..4b97a904e93 100644
--- a/include/qemu/vfio-helpers.h
+++ b/include/qemu/vfio-helpers.h
@@ -15,7 +15,8 @@ 
 
 typedef struct QEMUVFIOState QEMUVFIOState;
 
-QEMUVFIOState *qemu_vfio_open_pci(const char *device, Error **errp);
+QEMUVFIOState *qemu_vfio_open_pci(const char *device, size_t *min_page_size,
+                                  Error **errp);
 void qemu_vfio_close(QEMUVFIOState *s);
 int qemu_vfio_dma_map(QEMUVFIOState *s, void *host, size_t size,
                       bool temporary, uint64_t *iova_list, Error **errp);
diff --git a/block/nvme.c b/block/nvme.c
index 6f1ebdf031f..46b09b3a3a7 100644
--- a/block/nvme.c
+++ b/block/nvme.c
@@ -691,6 +691,7 @@  static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
     Error *local_err = NULL;
     volatile NvmeBar *regs = NULL;
     size_t device_page_size_min;
+    size_t device_page_size_max;
     size_t iommu_page_size_min = 4096;
 
     qemu_co_mutex_init(&s->dma_map_lock);
@@ -704,7 +705,7 @@  static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
         return ret;
     }
 
-    s->vfio = qemu_vfio_open_pci(device, errp);
+    s->vfio = qemu_vfio_open_pci(device, &iommu_page_size_min, errp);
     if (!s->vfio) {
         ret = -EINVAL;
         goto out;
@@ -737,6 +738,17 @@  static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
     }
 
     device_page_size_min = 1u << (12 + NVME_CAP_MPSMIN(cap));
+    device_page_size_max = 1u << (12 + NVME_CAP_MPSMAX(cap));
+    if (iommu_page_size_min > device_page_size_max) {
+        g_autofree char *iommu_page_size_s = size_to_str(iommu_page_size_min);
+        g_autofree char *device_page_size_s = size_to_str(device_page_size_max);
+
+        error_setg(errp, "IOMMU minimum page size (%s)"
+                         " too big for device (max %s)",
+                   iommu_page_size_s, device_page_size_s);
+        ret = -EINVAL;
+        goto out;
+    }
     s->page_size = MAX(iommu_page_size_min, device_page_size_min);
     s->doorbell_scale = (4 << NVME_CAP_DSTRD(cap)) / sizeof(uint32_t);
     bs->bl.opt_mem_alignment = s->page_size;
diff --git a/util/vfio-helpers.c b/util/vfio-helpers.c
index 488ddfca2a9..5e288dfa113 100644
--- a/util/vfio-helpers.c
+++ b/util/vfio-helpers.c
@@ -508,8 +508,14 @@  static void qemu_vfio_open_common(QEMUVFIOState *s)
 
 /**
  * Open a PCI device, e.g. "0000:00:01.0".
+ *
+ * @min_page_size: Pointer holding the minimum page size requested
+ *
+ * If the IOMMU can not be configured with @min_page_size, the minimum
+ * page size is stored in @min_page_size and -EINVAL is returned.
  */
-QEMUVFIOState *qemu_vfio_open_pci(const char *device, Error **errp)
+QEMUVFIOState *qemu_vfio_open_pci(const char *device, size_t *min_page_size,
+                                  Error **errp)
 {
     int r;
     QEMUVFIOState *s = g_new0(QEMUVFIOState, 1);