diff options
author | Philippe Mathieu-Daudé | 2020-10-29 10:33:04 +0100 |
---|---|---|
committer | Stefan Hajnoczi | 2020-11-03 20:06:22 +0100 |
commit | 4b19e9b8159b5eecf8e90c81c56c1a13547e411a (patch) | |
tree | cd0f435cda29e905d84b1ab8ed033e36f41c8e6d | |
parent | block/nvme: Align iov's va and size on host page size (diff) | |
download | qemu-4b19e9b8159b5eecf8e90c81c56c1a13547e411a.tar.gz qemu-4b19e9b8159b5eecf8e90c81c56c1a13547e411a.tar.xz qemu-4b19e9b8159b5eecf8e90c81c56c1a13547e411a.zip |
block/nvme: Fix use of write-only doorbells page on Aarch64 arch
qemu_vfio_pci_map_bar() calls mmap(), and mmap(2) states:
'offset' must be a multiple of the page size as returned
by sysconf(_SC_PAGE_SIZE).
In commit f68453237b9 we started to use an offset of 4K which
broke this contract on Aarch64 arch.
Fix by mapping at offset 0, and and accessing doorbells at offset=4K.
Fixes: f68453237b9 ("block/nvme: Map doorbells pages write-only")
Reported-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Tested-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-id: 20201029093306.1063879-24-philmd@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Tested-by: Eric Auger <eric.auger@redhat.com>
-rw-r--r-- | block/nvme.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/block/nvme.c b/block/nvme.c index f1e2fd34cd..c8ef69cbb2 100644 --- a/block/nvme.c +++ b/block/nvme.c @@ -94,6 +94,7 @@ typedef struct { struct BDRVNVMeState { AioContext *aio_context; QEMUVFIOState *vfio; + void *bar0_wo_map; /* Memory mapped registers */ volatile struct { uint32_t sq_tail; @@ -777,8 +778,10 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, } } - s->doorbells = qemu_vfio_pci_map_bar(s->vfio, 0, sizeof(NvmeBar), - NVME_DOORBELL_SIZE, PROT_WRITE, errp); + s->bar0_wo_map = qemu_vfio_pci_map_bar(s->vfio, 0, 0, + sizeof(NvmeBar) + NVME_DOORBELL_SIZE, + PROT_WRITE, errp); + s->doorbells = (void *)((uintptr_t)s->bar0_wo_map + sizeof(NvmeBar)); if (!s->doorbells) { ret = -EINVAL; goto out; @@ -910,8 +913,8 @@ static void nvme_close(BlockDriverState *bs) &s->irq_notifier[MSIX_SHARED_IRQ_IDX], false, NULL, NULL); event_notifier_cleanup(&s->irq_notifier[MSIX_SHARED_IRQ_IDX]); - qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->doorbells, - sizeof(NvmeBar), NVME_DOORBELL_SIZE); + qemu_vfio_pci_unmap_bar(s->vfio, 0, s->bar0_wo_map, + 0, sizeof(NvmeBar) + NVME_DOORBELL_SIZE); qemu_vfio_close(s->vfio); g_free(s->device); |