Hi,

On 10/27/20 2:55 PM, Philippe Mathieu-Daudé wrote:
> 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.au...@redhat.com>
> Signed-off-by: Philippe Mathieu-Daudé <phi...@redhat.com>
Reviewed-by: Eric Auger <eric.au...@redhat.com>

Eric

> ---
>  block/nvme.c | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
> 
> diff --git a/block/nvme.c b/block/nvme.c
> index c1c52bae44f..ff645eefe6a 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;
> @@ -778,8 +779,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;
> @@ -913,8 +916,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);
> 


Reply via email to