qemu/include/hw/virtio/virtio-access.h
<<
>>
Prefs
   1/*
   2 * Virtio Accessor Support: In case your target can change endian.
   3 *
   4 * Copyright IBM, Corp. 2013
   5 *
   6 * Authors:
   7 *  Rusty Russell   <rusty@au.ibm.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation, either version 2 of the License, or
  12 * (at your option) any later version.
  13 *
  14 */
  15
  16#ifndef QEMU_VIRTIO_ACCESS_H
  17#define QEMU_VIRTIO_ACCESS_H
  18
  19#include "exec/hwaddr.h"
  20#include "hw/virtio/virtio.h"
  21#include "hw/virtio/virtio-bus.h"
  22
  23#if defined(TARGET_PPC64) || defined(TARGET_ARM)
  24#define LEGACY_VIRTIO_IS_BIENDIAN 1
  25#endif
  26
  27static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
  28{
  29#if defined(LEGACY_VIRTIO_IS_BIENDIAN)
  30    return virtio_is_big_endian(vdev);
  31#elif defined(TARGET_WORDS_BIGENDIAN)
  32    if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
  33        /* Devices conforming to VIRTIO 1.0 or later are always LE. */
  34        return false;
  35    }
  36    return true;
  37#else
  38    return false;
  39#endif
  40}
  41
  42static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa)
  43{
  44    AddressSpace *dma_as = vdev->dma_as;
  45
  46    if (virtio_access_is_big_endian(vdev)) {
  47        return lduw_be_phys(dma_as, pa);
  48    }
  49    return lduw_le_phys(dma_as, pa);
  50}
  51
  52static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa)
  53{
  54    AddressSpace *dma_as = vdev->dma_as;
  55
  56    if (virtio_access_is_big_endian(vdev)) {
  57        return ldl_be_phys(dma_as, pa);
  58    }
  59    return ldl_le_phys(dma_as, pa);
  60}
  61
  62static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa)
  63{
  64    AddressSpace *dma_as = vdev->dma_as;
  65
  66    if (virtio_access_is_big_endian(vdev)) {
  67        return ldq_be_phys(dma_as, pa);
  68    }
  69    return ldq_le_phys(dma_as, pa);
  70}
  71
  72static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa,
  73                                   uint16_t value)
  74{
  75    AddressSpace *dma_as = vdev->dma_as;
  76
  77    if (virtio_access_is_big_endian(vdev)) {
  78        stw_be_phys(dma_as, pa, value);
  79    } else {
  80        stw_le_phys(dma_as, pa, value);
  81    }
  82}
  83
  84static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa,
  85                                   uint32_t value)
  86{
  87    AddressSpace *dma_as = vdev->dma_as;
  88
  89    if (virtio_access_is_big_endian(vdev)) {
  90        stl_be_phys(dma_as, pa, value);
  91    } else {
  92        stl_le_phys(dma_as, pa, value);
  93    }
  94}
  95
  96static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v)
  97{
  98    if (virtio_access_is_big_endian(vdev)) {
  99        stw_be_p(ptr, v);
 100    } else {
 101        stw_le_p(ptr, v);
 102    }
 103}
 104
 105static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v)
 106{
 107    if (virtio_access_is_big_endian(vdev)) {
 108        stl_be_p(ptr, v);
 109    } else {
 110        stl_le_p(ptr, v);
 111    }
 112}
 113
 114static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v)
 115{
 116    if (virtio_access_is_big_endian(vdev)) {
 117        stq_be_p(ptr, v);
 118    } else {
 119        stq_le_p(ptr, v);
 120    }
 121}
 122
 123static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr)
 124{
 125    if (virtio_access_is_big_endian(vdev)) {
 126        return lduw_be_p(ptr);
 127    } else {
 128        return lduw_le_p(ptr);
 129    }
 130}
 131
 132static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr)
 133{
 134    if (virtio_access_is_big_endian(vdev)) {
 135        return ldl_be_p(ptr);
 136    } else {
 137        return ldl_le_p(ptr);
 138    }
 139}
 140
 141static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr)
 142{
 143    if (virtio_access_is_big_endian(vdev)) {
 144        return ldq_be_p(ptr);
 145    } else {
 146        return ldq_le_p(ptr);
 147    }
 148}
 149
 150static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s)
 151{
 152#ifdef HOST_WORDS_BIGENDIAN
 153    return virtio_access_is_big_endian(vdev) ? s : bswap16(s);
 154#else
 155    return virtio_access_is_big_endian(vdev) ? bswap16(s) : s;
 156#endif
 157}
 158
 159static inline uint16_t virtio_lduw_phys_cached(VirtIODevice *vdev,
 160                                               MemoryRegionCache *cache,
 161                                               hwaddr pa)
 162{
 163    if (virtio_access_is_big_endian(vdev)) {
 164        return lduw_be_phys_cached(cache, pa);
 165    }
 166    return lduw_le_phys_cached(cache, pa);
 167}
 168
 169static inline uint32_t virtio_ldl_phys_cached(VirtIODevice *vdev,
 170                                              MemoryRegionCache *cache,
 171                                              hwaddr pa)
 172{
 173    if (virtio_access_is_big_endian(vdev)) {
 174        return ldl_be_phys_cached(cache, pa);
 175    }
 176    return ldl_le_phys_cached(cache, pa);
 177}
 178
 179static inline uint64_t virtio_ldq_phys_cached(VirtIODevice *vdev,
 180                                              MemoryRegionCache *cache,
 181                                              hwaddr pa)
 182{
 183    if (virtio_access_is_big_endian(vdev)) {
 184        return ldq_be_phys_cached(cache, pa);
 185    }
 186    return ldq_le_phys_cached(cache, pa);
 187}
 188
 189static inline void virtio_stw_phys_cached(VirtIODevice *vdev,
 190                                          MemoryRegionCache *cache,
 191                                          hwaddr pa, uint16_t value)
 192{
 193    if (virtio_access_is_big_endian(vdev)) {
 194        stw_be_phys_cached(cache, pa, value);
 195    } else {
 196        stw_le_phys_cached(cache, pa, value);
 197    }
 198}
 199
 200static inline void virtio_stl_phys_cached(VirtIODevice *vdev,
 201                                          MemoryRegionCache *cache,
 202                                          hwaddr pa, uint32_t value)
 203{
 204    if (virtio_access_is_big_endian(vdev)) {
 205        stl_be_phys_cached(cache, pa, value);
 206    } else {
 207        stl_le_phys_cached(cache, pa, value);
 208    }
 209}
 210
 211static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s)
 212{
 213    *s = virtio_tswap16(vdev, *s);
 214}
 215
 216static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s)
 217{
 218#ifdef HOST_WORDS_BIGENDIAN
 219    return virtio_access_is_big_endian(vdev) ? s : bswap32(s);
 220#else
 221    return virtio_access_is_big_endian(vdev) ? bswap32(s) : s;
 222#endif
 223}
 224
 225static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s)
 226{
 227    *s = virtio_tswap32(vdev, *s);
 228}
 229
 230static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s)
 231{
 232#ifdef HOST_WORDS_BIGENDIAN
 233    return virtio_access_is_big_endian(vdev) ? s : bswap64(s);
 234#else
 235    return virtio_access_is_big_endian(vdev) ? bswap64(s) : s;
 236#endif
 237}
 238
 239static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s)
 240{
 241    *s = virtio_tswap64(vdev, *s);
 242}
 243#endif /* QEMU_VIRTIO_ACCESS_H */
 244