qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v7 36/42] memory: Access MemoryRegion with endia


From: Richard Henderson
Subject: Re: [Qemu-devel] [PATCH v7 36/42] memory: Access MemoryRegion with endianness
Date: Sun, 18 Aug 2019 13:22:57 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0

On 8/16/19 8:38 AM, address@hidden wrote:
> Preparation for collapsing the two byte swaps adjust_endianness and
> handle_bswap into the former.
> 
> Call memory_region_dispatch_{read|write} with endianness encoded into
> the "MemOp op" operand.
> 
> This patch does not change any behaviour as
> memory_region_dispatch_{read|write} is yet to handle the endianness.
> 
> Once it does handle endianness, callers with byte swaps can collapse
> them into adjust_endianness.
> 
> Signed-off-by: Tony Nguyen <address@hidden>
> ---
>  accel/tcg/cputlb.c       |  6 ++++--
>  exec.c                   |  5 +++--
>  hw/intc/armv7m_nvic.c    | 15 ++++++++-------
>  hw/s390x/s390-pci-inst.c |  6 ++++--
>  hw/vfio/pci-quirks.c     |  5 +++--
>  hw/virtio/virtio-pci.c   |  6 ++++--
>  memory_ldst.inc.c        | 18 ++++++++++++------
>  7 files changed, 38 insertions(+), 23 deletions(-)
> 
> diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
> index 6c83878..0aff6a3 100644
> --- a/accel/tcg/cputlb.c
> +++ b/accel/tcg/cputlb.c
> @@ -906,7 +906,8 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry 
> *iotlbentry,
>          qemu_mutex_lock_iothread();
>          locked = true;
>      }
> -    r = memory_region_dispatch_read(mr, mr_offset, &val, size_memop(size),
> +    r = memory_region_dispatch_read(mr, mr_offset, &val,
> +                                    size_memop(size) | MO_TE,
>                                      iotlbentry->attrs);
>      if (r != MEMTX_OK) {
>          hwaddr physaddr = mr_offset +
> @@ -947,7 +948,8 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry 
> *iotlbentry,
>          qemu_mutex_lock_iothread();
>          locked = true;
>      }
> -    r = memory_region_dispatch_write(mr, mr_offset, val, size_memop(size),
> +    r = memory_region_dispatch_write(mr, mr_offset, val,
> +                                     size_memop(size) | MO_TE,
>                                       iotlbentry->attrs);

Ok.  Conversion to target-endian via handle_bswap() in the callers.

> diff --git a/exec.c b/exec.c
> index 303f9a7..562fb5b 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -3335,7 +3335,8 @@ static MemTxResult flatview_write_continue(FlatView 
> *fv, hwaddr addr,
>                 potential bugs */
>              val = ldn_p(buf, l);
>              result |= memory_region_dispatch_write(mr, addr1, val,
> -                                                   size_memop(l), attrs);
> +                                                   size_memop(l) | MO_TE,
> +                                                   attrs);
>          } else {
>              /* RAM case */
>              ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
> @@ -3397,7 +3398,7 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr 
> addr,
>              release_lock |= prepare_mmio_access(mr);
>              l = memory_access_size(mr, l, addr1);
>              result |= memory_region_dispatch_read(mr, addr1, &val,
> -                                                  size_memop(l), attrs);
> +                                                  size_memop(l) | MO_TE, 
> attrs);
>              stn_p(buf, l, val);

Ok.  Please add comments:

    /*
     * TODO: Merge bswap from ldn_p into memory_region_dispatch_write
     * by using ldn_he_p and dropping MO_TE to get a host-endian value.
     */

and similar for the store.

This must be delayed until after patch 38, when the MO_BSWAP component of the
MemOp is operated on by memory_region_dispatch_*.

> --- a/hw/intc/armv7m_nvic.c
> +++ b/hw/intc/armv7m_nvic.c
> @@ -2346,8 +2346,8 @@ static MemTxResult nvic_sysreg_ns_write(void *opaque, 
> hwaddr addr,
>      if (attrs.secure) {
>          /* S accesses to the alias act like NS accesses to the real region */
>          attrs.secure = 0;
> -        return memory_region_dispatch_write(mr, addr, value, 
> size_memop(size),
> -                                            attrs);
> +        return memory_region_dispatch_write(mr, addr, value,
> +                                            size_memop(size) | MO_TE, attrs);
>      } else {
>          /* NS attrs are RAZ/WI for privileged, and BusFault for user */
>          if (attrs.user) {
> @@ -2366,8 +2366,8 @@ static MemTxResult nvic_sysreg_ns_read(void *opaque, 
> hwaddr addr,
>      if (attrs.secure) {
>          /* S accesses to the alias act like NS accesses to the real region */
>          attrs.secure = 0;
> -        return memory_region_dispatch_read(mr, addr, data, size_memop(size),
> -                                           attrs);
> +        return memory_region_dispatch_read(mr, addr, data,
> +                                           size_memop(size) | MO_TE, attrs);
>      } else {
>          /* NS attrs are RAZ/WI for privileged, and BusFault for user */
>          if (attrs.user) {
> @@ -2393,8 +2393,8 @@ static MemTxResult nvic_systick_write(void *opaque, 
> hwaddr addr,
> 
>      /* Direct the access to the correct systick */
>      mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systick[attrs.secure]), 
> 0);
> -    return memory_region_dispatch_write(mr, addr, value, size_memop(size),
> -                                        attrs);
> +    return memory_region_dispatch_write(mr, addr, value,
> +                                        size_memop(size) | MO_TE, attrs);
>  }
> 
>  static MemTxResult nvic_systick_read(void *opaque, hwaddr addr,
> @@ -2406,7 +2406,8 @@ static MemTxResult nvic_systick_read(void *opaque, 
> hwaddr addr,
> 
>      /* Direct the access to the correct systick */
>      mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systick[attrs.secure]), 
> 0);
> -    return memory_region_dispatch_read(mr, addr, data, size_memop(size), 
> attrs);
> +    return memory_region_dispatch_read(mr, addr, data, size_memop(size) | 
> MO_TE,
> +                                       attrs);
>  }

Ok.

> 
>  static const MemoryRegionOps nvic_systick_ops = {
> diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
> index 0e92a37..272cb28 100644
> --- a/hw/s390x/s390-pci-inst.c
> +++ b/hw/s390x/s390-pci-inst.c
> @@ -373,7 +373,8 @@ static MemTxResult zpci_read_bar(S390PCIBusDevice *pbdev, 
> uint8_t pcias,
>      mr = pbdev->pdev->io_regions[pcias].memory;
>      mr = s390_get_subregion(mr, offset, len);
>      offset -= mr->addr;
> -    return memory_region_dispatch_read(mr, offset, data, size_memop(len),
> +    return memory_region_dispatch_read(mr, offset, data,
> +                                       size_memop(len) | MO_LE,
>                                         MEMTXATTRS_UNSPECIFIED);
>  }
> 
> @@ -472,7 +473,8 @@ static MemTxResult zpci_write_bar(S390PCIBusDevice 
> *pbdev, uint8_t pcias,
>      mr = pbdev->pdev->io_regions[pcias].memory;
>      mr = s390_get_subregion(mr, offset, len);
>      offset -= mr->addr;
> -    return memory_region_dispatch_write(mr, offset, data, size_memop(len),
> +    return memory_region_dispatch_write(mr, offset, data,
> +                                        size_memop(len) | MO_LE,
>                                          MEMTXATTRS_UNSPECIFIED);
>  }

How did you derive MO_LE here?

I realize that pci tends to imply LE, but this is called from
pcilg_service_call, which is an s390 instruction, Which normally implies BE.


> 
> diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c
> index d5c0268..53db1c3 100644
> --- a/hw/vfio/pci-quirks.c
> +++ b/hw/vfio/pci-quirks.c
> @@ -1072,7 +1072,8 @@ static void vfio_rtl8168_quirk_address_write(void 
> *opaque, hwaddr addr,
> 
>                  /* Write to the proper guest MSI-X table instead */
>                  memory_region_dispatch_write(&vdev->pdev.msix_table_mmio,
> -                                             offset, val, size_memop(size),
> +                                             offset, val,
> +                                             size_memop(size) | MO_LE,
>                                               MEMTXATTRS_UNSPECIFIED);
>              }
>              return; /* Do not write guest MSI-X data to hardware */
> @@ -1103,7 +1104,7 @@ static uint64_t vfio_rtl8168_quirk_data_read(void 
> *opaque,
>      if (rtl->enabled && (vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX)) {
>          hwaddr offset = rtl->addr & 0xfff;
>          memory_region_dispatch_read(&vdev->pdev.msix_table_mmio, offset,
> -                                    &data, size_memop(size),
> +                                    &data, size_memop(size) | MO_LE,
>                                      MEMTXATTRS_UNSPECIFIED);
>          trace_vfio_quirk_rtl8168_msix_read(vdev->vbasedev.name, offset, 
> data);
>      }


Hmm.  We have .endianness = DEVICE_LITTLE_ENDIAN, so we probably already did
any bswap on input to this function.  Surely any further swapping should be
suppressed.  I assume MSI-X rtl8168 is only used by x86 guests, and we would
not notice a problem testing this on an x86 host.


> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index b929e44..ad06c12 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -551,7 +551,8 @@ void virtio_address_space_write(VirtIOPCIProxy *proxy, 
> hwaddr addr,
>          /* As length is under guest control, handle illegal values. */
>          return;
>      }
> -    memory_region_dispatch_write(mr, addr, val, size_memop(len),
> +    /* FIXME: memory_region_dispatch_write ignores MO_BSWAP.  */
> +    memory_region_dispatch_write(mr, addr, val, size_memop(len) | MO_LE,
>                                   MEMTXATTRS_UNSPECIFIED);
>  }
> 
> @@ -575,7 +576,8 @@ virtio_address_space_read(VirtIOPCIProxy *proxy, hwaddr 
> addr,
>      /* Make sure caller aligned buf properly */
>      assert(!(((uintptr_t)buf) & (len - 1)));
> 
> -    memory_region_dispatch_read(mr, addr, &val, size_memop(len),
> +    /* FIXME: memory_region_dispatch_read ignores MO_BSWAP.  */
> +    memory_region_dispatch_read(mr, addr, &val, size_memop(len) | MO_LE,
>                                  MEMTXATTRS_UNSPECIFIED);
>      switch (len) {
>      case 1:

Ok, cpu_to_le32 etc above.

> diff --git a/memory_ldst.inc.c b/memory_ldst.inc.c
> index d08fc79..482e4b3 100644
> --- a/memory_ldst.inc.c
> +++ b/memory_ldst.inc.c
> @@ -37,7 +37,8 @@ static inline uint32_t glue(address_space_ldl_internal, 
> SUFFIX)(ARG1_DECL,
>          release_lock |= prepare_mmio_access(mr);
> 
>          /* I/O case */
> -        r = memory_region_dispatch_read(mr, addr1, &val, MO_32, attrs);
> +        /* FIXME: memory_region_dispatch_read ignores MO_BSWAP.  */
> +        r = memory_region_dispatch_read(mr, addr1, &val, MO_32 | endian, 
> attrs);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == MO_LE) {
>              val = bswap32(val);
> @@ -112,7 +113,8 @@ static inline uint64_t glue(address_space_ldq_internal, 
> SUFFIX)(ARG1_DECL,
>          release_lock |= prepare_mmio_access(mr);
> 
>          /* I/O case */
> -        r = memory_region_dispatch_read(mr, addr1, &val, MO_64, attrs);
> +        /* FIXME: memory_region_dispatch_read ignores MO_BSWAP.  */
> +        r = memory_region_dispatch_read(mr, addr1, &val, MO_64 | endian, 
> attrs);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == MO_LE) {
>              val = bswap64(val);
> @@ -221,7 +223,8 @@ static inline uint32_t glue(address_space_lduw_internal, 
> SUFFIX)(ARG1_DECL,
>          release_lock |= prepare_mmio_access(mr);
> 
>          /* I/O case */
> -        r = memory_region_dispatch_read(mr, addr1, &val, MO_16, attrs);
> +        /* FIXME: memory_region_dispatch_read ignores MO_BSWAP.  */
> +        r = memory_region_dispatch_read(mr, addr1, &val, MO_16 | endian, 
> attrs);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == MO_LE) {
>              val = bswap16(val);
> @@ -342,7 +345,8 @@ static inline void glue(address_space_stl_internal, 
> SUFFIX)(ARG1_DECL,
>              val = bswap32(val);
>          }
>  #endif
> -        r = memory_region_dispatch_write(mr, addr1, val, MO_32, attrs);
> +        /* FIXME: memory_region_dispatch_write ignores MO_BSWAP.  */
> +        r = memory_region_dispatch_write(mr, addr1, val, MO_32 | endian, 
> attrs);
>      } else {
>          /* RAM case */
>          ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
> @@ -447,7 +451,8 @@ static inline void glue(address_space_stw_internal, 
> SUFFIX)(ARG1_DECL,
>              val = bswap16(val);
>          }
>  #endif
> -        r = memory_region_dispatch_write(mr, addr1, val, MO_16, attrs);
> +        /* FIXME: memory_region_dispatch_write ignores MO_BSWAP.  */
> +        r = memory_region_dispatch_write(mr, addr1, val, MO_16 | endian, 
> attrs);
>      } else {
>          /* RAM case */
>          ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
> @@ -520,7 +525,8 @@ static void glue(address_space_stq_internal, 
> SUFFIX)(ARG1_DECL,
>              val = bswap64(val);
>          }
>  #endif
> -        r = memory_region_dispatch_write(mr, addr1, val, MO_64, attrs);
> +        /* FIXME: memory_region_dispatch_write ignores MO_BSWAP.  */
> +        r = memory_region_dispatch_write(mr, addr1, val, MO_64 | endian, 
> attrs);

Ok.  Since you're splitting out the device changes, you'll need a conversion
function for now:

MemOp devend_memop(enum device_endian end)
{
    static MemOp conv[] = {
        [DEVICE_LITTLE_ENDIAN] = MO_LE,
        [DEVICE_BIG_ENDIAN] = MO_BE,
        [DEVICE_NATIVE_ENDIAN] = MO_TE,
        [DEVICE_HOST_ENDIAN] = 0,
    };
    switch (end) {
    case DEVICE_LITTLE_ENDIAN:
    case DEVICE_BIG_ENDIAN:
    case DEVICE_NATIVE_ENDIAN:
    case DEVICE_HOST_ENDIAN:
        return conv[end];
    default:
        g_assert_not_reached();
    }
}

Probably declared in include/exec/memory.h and implemented in memory.c.


r~



reply via email to

[Prev in Thread] Current Thread [Next in Thread]