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