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é <phi...@redhat.com> --- include/qemu/vfio-helpers.h | 3 ++- block/nvme.c | 14 +++++++++++++- util/vfio-helpers.c | 8 +++++++- 3 files changed, 22 insertions(+), 3 deletions(-) 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); -- 2.26.2