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 "exec/address-spaces.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    if (virtio_access_is_big_endian(vdev)) {
  44        return lduw_be_phys(&address_space_memory, pa);
  45    }
  46    return lduw_le_phys(&address_space_memory, pa);
  47}
  48
  49static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa)
  50{
  51    if (virtio_access_is_big_endian(vdev)) {
  52        return ldl_be_phys(&address_space_memory, pa);
  53    }
  54    return ldl_le_phys(&address_space_memory, pa);
  55}
  56
  57static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa)
  58{
  59    if (virtio_access_is_big_endian(vdev)) {
  60        return ldq_be_phys(&address_space_memory, pa);
  61    }
  62    return ldq_le_phys(&address_space_memory, pa);
  63}
  64
  65static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa,
  66                                   uint16_t value)
  67{
  68    if (virtio_access_is_big_endian(vdev)) {
  69        stw_be_phys(&address_space_memory, pa, value);
  70    } else {
  71        stw_le_phys(&address_space_memory, pa, value);
  72    }
  73}
  74
  75static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa,
  76                                   uint32_t value)
  77{
  78    if (virtio_access_is_big_endian(vdev)) {
  79        stl_be_phys(&address_space_memory, pa, value);
  80    } else {
  81        stl_le_phys(&address_space_memory, pa, value);
  82    }
  83}
  84
  85static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v)
  86{
  87    if (virtio_access_is_big_endian(vdev)) {
  88        stw_be_p(ptr, v);
  89    } else {
  90        stw_le_p(ptr, v);
  91    }
  92}
  93
  94static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v)
  95{
  96    if (virtio_access_is_big_endian(vdev)) {
  97        stl_be_p(ptr, v);
  98    } else {
  99        stl_le_p(ptr, v);
 100    }
 101}
 102
 103static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v)
 104{
 105    if (virtio_access_is_big_endian(vdev)) {
 106        stq_be_p(ptr, v);
 107    } else {
 108        stq_le_p(ptr, v);
 109    }
 110}
 111
 112static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr)
 113{
 114    if (virtio_access_is_big_endian(vdev)) {
 115        return lduw_be_p(ptr);
 116    } else {
 117        return lduw_le_p(ptr);
 118    }
 119}
 120
 121static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr)
 122{
 123    if (virtio_access_is_big_endian(vdev)) {
 124        return ldl_be_p(ptr);
 125    } else {
 126        return ldl_le_p(ptr);
 127    }
 128}
 129
 130static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr)
 131{
 132    if (virtio_access_is_big_endian(vdev)) {
 133        return ldq_be_p(ptr);
 134    } else {
 135        return ldq_le_p(ptr);
 136    }
 137}
 138
 139static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s)
 140{
 141#ifdef HOST_WORDS_BIGENDIAN
 142    return virtio_access_is_big_endian(vdev) ? s : bswap16(s);
 143#else
 144    return virtio_access_is_big_endian(vdev) ? bswap16(s) : s;
 145#endif
 146}
 147
 148static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s)
 149{
 150    *s = virtio_tswap16(vdev, *s);
 151}
 152
 153static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s)
 154{
 155#ifdef HOST_WORDS_BIGENDIAN
 156    return virtio_access_is_big_endian(vdev) ? s : bswap32(s);
 157#else
 158    return virtio_access_is_big_endian(vdev) ? bswap32(s) : s;
 159#endif
 160}
 161
 162static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s)
 163{
 164    *s = virtio_tswap32(vdev, *s);
 165}
 166
 167static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s)
 168{
 169#ifdef HOST_WORDS_BIGENDIAN
 170    return virtio_access_is_big_endian(vdev) ? s : bswap64(s);
 171#else
 172    return virtio_access_is_big_endian(vdev) ? bswap64(s) : s;
 173#endif
 174}
 175
 176static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s)
 177{
 178    *s = virtio_tswap64(vdev, *s);
 179}
 180#endif /* QEMU_VIRTIO_ACCESS_H */
 181