cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

bswap.h (13705B)


      1#ifndef BSWAP_H
      2#define BSWAP_H
      3
      4#ifdef CONFIG_MACHINE_BSWAP_H
      5# include <sys/endian.h>
      6# include <machine/bswap.h>
      7#elif defined(__FreeBSD__)
      8# include <sys/endian.h>
      9#elif defined(__HAIKU__)
     10# include <endian.h>
     11#elif defined(CONFIG_BYTESWAP_H)
     12# include <byteswap.h>
     13#define BSWAP_FROM_BYTESWAP
     14# else
     15#define BSWAP_FROM_FALLBACKS
     16#endif /* ! CONFIG_MACHINE_BSWAP_H */
     17
     18#ifdef __cplusplus
     19extern "C" {
     20#endif
     21
     22#include "fpu/softfloat-types.h"
     23
     24#ifdef BSWAP_FROM_BYTESWAP
     25static inline uint16_t bswap16(uint16_t x)
     26{
     27    return bswap_16(x);
     28}
     29
     30static inline uint32_t bswap32(uint32_t x)
     31{
     32    return bswap_32(x);
     33}
     34
     35static inline uint64_t bswap64(uint64_t x)
     36{
     37    return bswap_64(x);
     38}
     39#endif
     40
     41#ifdef BSWAP_FROM_FALLBACKS
     42static inline uint16_t bswap16(uint16_t x)
     43{
     44    return (((x & 0x00ff) << 8) |
     45            ((x & 0xff00) >> 8));
     46}
     47
     48static inline uint32_t bswap32(uint32_t x)
     49{
     50    return (((x & 0x000000ffU) << 24) |
     51            ((x & 0x0000ff00U) <<  8) |
     52            ((x & 0x00ff0000U) >>  8) |
     53            ((x & 0xff000000U) >> 24));
     54}
     55
     56static inline uint64_t bswap64(uint64_t x)
     57{
     58    return (((x & 0x00000000000000ffULL) << 56) |
     59            ((x & 0x000000000000ff00ULL) << 40) |
     60            ((x & 0x0000000000ff0000ULL) << 24) |
     61            ((x & 0x00000000ff000000ULL) <<  8) |
     62            ((x & 0x000000ff00000000ULL) >>  8) |
     63            ((x & 0x0000ff0000000000ULL) >> 24) |
     64            ((x & 0x00ff000000000000ULL) >> 40) |
     65            ((x & 0xff00000000000000ULL) >> 56));
     66}
     67#endif
     68
     69#undef BSWAP_FROM_BYTESWAP
     70#undef BSWAP_FROM_FALLBACKS
     71
     72static inline void bswap16s(uint16_t *s)
     73{
     74    *s = bswap16(*s);
     75}
     76
     77static inline void bswap32s(uint32_t *s)
     78{
     79    *s = bswap32(*s);
     80}
     81
     82static inline void bswap64s(uint64_t *s)
     83{
     84    *s = bswap64(*s);
     85}
     86
     87#if defined(HOST_WORDS_BIGENDIAN)
     88#define be_bswap(v, size) (v)
     89#define le_bswap(v, size) glue(bswap, size)(v)
     90#define be_bswaps(v, size)
     91#define le_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
     92#else
     93#define le_bswap(v, size) (v)
     94#define be_bswap(v, size) glue(bswap, size)(v)
     95#define le_bswaps(v, size)
     96#define be_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
     97#endif
     98
     99/**
    100 * Endianness conversion functions between host cpu and specified endianness.
    101 * (We list the complete set of prototypes produced by the macros below
    102 * to assist people who search the headers to find their definitions.)
    103 *
    104 * uint16_t le16_to_cpu(uint16_t v);
    105 * uint32_t le32_to_cpu(uint32_t v);
    106 * uint64_t le64_to_cpu(uint64_t v);
    107 * uint16_t be16_to_cpu(uint16_t v);
    108 * uint32_t be32_to_cpu(uint32_t v);
    109 * uint64_t be64_to_cpu(uint64_t v);
    110 *
    111 * Convert the value @v from the specified format to the native
    112 * endianness of the host CPU by byteswapping if necessary, and
    113 * return the converted value.
    114 *
    115 * uint16_t cpu_to_le16(uint16_t v);
    116 * uint32_t cpu_to_le32(uint32_t v);
    117 * uint64_t cpu_to_le64(uint64_t v);
    118 * uint16_t cpu_to_be16(uint16_t v);
    119 * uint32_t cpu_to_be32(uint32_t v);
    120 * uint64_t cpu_to_be64(uint64_t v);
    121 *
    122 * Convert the value @v from the native endianness of the host CPU to
    123 * the specified format by byteswapping if necessary, and return
    124 * the converted value.
    125 *
    126 * void le16_to_cpus(uint16_t *v);
    127 * void le32_to_cpus(uint32_t *v);
    128 * void le64_to_cpus(uint64_t *v);
    129 * void be16_to_cpus(uint16_t *v);
    130 * void be32_to_cpus(uint32_t *v);
    131 * void be64_to_cpus(uint64_t *v);
    132 *
    133 * Do an in-place conversion of the value pointed to by @v from the
    134 * specified format to the native endianness of the host CPU.
    135 *
    136 * void cpu_to_le16s(uint16_t *v);
    137 * void cpu_to_le32s(uint32_t *v);
    138 * void cpu_to_le64s(uint64_t *v);
    139 * void cpu_to_be16s(uint16_t *v);
    140 * void cpu_to_be32s(uint32_t *v);
    141 * void cpu_to_be64s(uint64_t *v);
    142 *
    143 * Do an in-place conversion of the value pointed to by @v from the
    144 * native endianness of the host CPU to the specified format.
    145 *
    146 * Both X_to_cpu() and cpu_to_X() perform the same operation; you
    147 * should use whichever one is better documenting of the function your
    148 * code is performing.
    149 *
    150 * Do not use these functions for conversion of values which are in guest
    151 * memory, since the data may not be sufficiently aligned for the host CPU's
    152 * load and store instructions. Instead you should use the ld*_p() and
    153 * st*_p() functions, which perform loads and stores of data of any
    154 * required size and endianness and handle possible misalignment.
    155 */
    156
    157#define CPU_CONVERT(endian, size, type)\
    158static inline type endian ## size ## _to_cpu(type v)\
    159{\
    160    return glue(endian, _bswap)(v, size);\
    161}\
    162\
    163static inline type cpu_to_ ## endian ## size(type v)\
    164{\
    165    return glue(endian, _bswap)(v, size);\
    166}\
    167\
    168static inline void endian ## size ## _to_cpus(type *p)\
    169{\
    170    glue(endian, _bswaps)(p, size);\
    171}\
    172\
    173static inline void cpu_to_ ## endian ## size ## s(type *p)\
    174{\
    175    glue(endian, _bswaps)(p, size);\
    176}
    177
    178CPU_CONVERT(be, 16, uint16_t)
    179CPU_CONVERT(be, 32, uint32_t)
    180CPU_CONVERT(be, 64, uint64_t)
    181
    182CPU_CONVERT(le, 16, uint16_t)
    183CPU_CONVERT(le, 32, uint32_t)
    184CPU_CONVERT(le, 64, uint64_t)
    185
    186/*
    187 * Same as cpu_to_le{16,32}, except that gcc will figure the result is
    188 * a compile-time constant if you pass in a constant.  So this can be
    189 * used to initialize static variables.
    190 */
    191#if defined(HOST_WORDS_BIGENDIAN)
    192# define const_le32(_x)                          \
    193    ((((_x) & 0x000000ffU) << 24) |              \
    194     (((_x) & 0x0000ff00U) <<  8) |              \
    195     (((_x) & 0x00ff0000U) >>  8) |              \
    196     (((_x) & 0xff000000U) >> 24))
    197# define const_le16(_x)                          \
    198    ((((_x) & 0x00ff) << 8) |                    \
    199     (((_x) & 0xff00) >> 8))
    200#else
    201# define const_le32(_x) (_x)
    202# define const_le16(_x) (_x)
    203#endif
    204
    205/* Unions for reinterpreting between floats and integers.  */
    206
    207typedef union {
    208    float32 f;
    209    uint32_t l;
    210} CPU_FloatU;
    211
    212typedef union {
    213    float64 d;
    214#if defined(HOST_WORDS_BIGENDIAN)
    215    struct {
    216        uint32_t upper;
    217        uint32_t lower;
    218    } l;
    219#else
    220    struct {
    221        uint32_t lower;
    222        uint32_t upper;
    223    } l;
    224#endif
    225    uint64_t ll;
    226} CPU_DoubleU;
    227
    228typedef union {
    229     floatx80 d;
    230     struct {
    231         uint64_t lower;
    232         uint16_t upper;
    233     } l;
    234} CPU_LDoubleU;
    235
    236typedef union {
    237    float128 q;
    238#if defined(HOST_WORDS_BIGENDIAN)
    239    struct {
    240        uint32_t upmost;
    241        uint32_t upper;
    242        uint32_t lower;
    243        uint32_t lowest;
    244    } l;
    245    struct {
    246        uint64_t upper;
    247        uint64_t lower;
    248    } ll;
    249#else
    250    struct {
    251        uint32_t lowest;
    252        uint32_t lower;
    253        uint32_t upper;
    254        uint32_t upmost;
    255    } l;
    256    struct {
    257        uint64_t lower;
    258        uint64_t upper;
    259    } ll;
    260#endif
    261} CPU_QuadU;
    262
    263/* unaligned/endian-independent pointer access */
    264
    265/*
    266 * the generic syntax is:
    267 *
    268 * load: ld{type}{sign}{size}_{endian}_p(ptr)
    269 *
    270 * store: st{type}{size}_{endian}_p(ptr, val)
    271 *
    272 * Note there are small differences with the softmmu access API!
    273 *
    274 * type is:
    275 * (empty): integer access
    276 *   f    : float access
    277 *
    278 * sign is:
    279 * (empty): for 32 or 64 bit sizes (including floats and doubles)
    280 *   u    : unsigned
    281 *   s    : signed
    282 *
    283 * size is:
    284 *   b: 8 bits
    285 *   w: 16 bits
    286 *   l: 32 bits
    287 *   q: 64 bits
    288 *
    289 * endian is:
    290 *   he   : host endian
    291 *   be   : big endian
    292 *   le   : little endian
    293 *   te   : target endian
    294 * (except for byte accesses, which have no endian infix).
    295 *
    296 * The target endian accessors are obviously only available to source
    297 * files which are built per-target; they are defined in cpu-all.h.
    298 *
    299 * In all cases these functions take a host pointer.
    300 * For accessors that take a guest address rather than a
    301 * host address, see the cpu_{ld,st}_* accessors defined in
    302 * cpu_ldst.h.
    303 *
    304 * For cases where the size to be used is not fixed at compile time,
    305 * there are
    306 *  stn_{endian}_p(ptr, sz, val)
    307 * which stores @val to @ptr as an @endian-order number @sz bytes in size
    308 * and
    309 *  ldn_{endian}_p(ptr, sz)
    310 * which loads @sz bytes from @ptr as an unsigned @endian-order number
    311 * and returns it in a uint64_t.
    312 */
    313
    314static inline int ldub_p(const void *ptr)
    315{
    316    return *(uint8_t *)ptr;
    317}
    318
    319static inline int ldsb_p(const void *ptr)
    320{
    321    return *(int8_t *)ptr;
    322}
    323
    324static inline void stb_p(void *ptr, uint8_t v)
    325{
    326    *(uint8_t *)ptr = v;
    327}
    328
    329/*
    330 * Any compiler worth its salt will turn these memcpy into native unaligned
    331 * operations.  Thus we don't need to play games with packed attributes, or
    332 * inline byte-by-byte stores.
    333 * Some compilation environments (eg some fortify-source implementations)
    334 * may intercept memcpy() in a way that defeats the compiler optimization,
    335 * though, so we use __builtin_memcpy() to give ourselves the best chance
    336 * of good performance.
    337 */
    338
    339static inline int lduw_he_p(const void *ptr)
    340{
    341    uint16_t r;
    342    __builtin_memcpy(&r, ptr, sizeof(r));
    343    return r;
    344}
    345
    346static inline int ldsw_he_p(const void *ptr)
    347{
    348    int16_t r;
    349    __builtin_memcpy(&r, ptr, sizeof(r));
    350    return r;
    351}
    352
    353static inline void stw_he_p(void *ptr, uint16_t v)
    354{
    355    __builtin_memcpy(ptr, &v, sizeof(v));
    356}
    357
    358static inline int ldl_he_p(const void *ptr)
    359{
    360    int32_t r;
    361    __builtin_memcpy(&r, ptr, sizeof(r));
    362    return r;
    363}
    364
    365static inline void stl_he_p(void *ptr, uint32_t v)
    366{
    367    __builtin_memcpy(ptr, &v, sizeof(v));
    368}
    369
    370static inline uint64_t ldq_he_p(const void *ptr)
    371{
    372    uint64_t r;
    373    __builtin_memcpy(&r, ptr, sizeof(r));
    374    return r;
    375}
    376
    377static inline void stq_he_p(void *ptr, uint64_t v)
    378{
    379    __builtin_memcpy(ptr, &v, sizeof(v));
    380}
    381
    382static inline int lduw_le_p(const void *ptr)
    383{
    384    return (uint16_t)le_bswap(lduw_he_p(ptr), 16);
    385}
    386
    387static inline int ldsw_le_p(const void *ptr)
    388{
    389    return (int16_t)le_bswap(lduw_he_p(ptr), 16);
    390}
    391
    392static inline int ldl_le_p(const void *ptr)
    393{
    394    return le_bswap(ldl_he_p(ptr), 32);
    395}
    396
    397static inline uint64_t ldq_le_p(const void *ptr)
    398{
    399    return le_bswap(ldq_he_p(ptr), 64);
    400}
    401
    402static inline void stw_le_p(void *ptr, uint16_t v)
    403{
    404    stw_he_p(ptr, le_bswap(v, 16));
    405}
    406
    407static inline void stl_le_p(void *ptr, uint32_t v)
    408{
    409    stl_he_p(ptr, le_bswap(v, 32));
    410}
    411
    412static inline void stq_le_p(void *ptr, uint64_t v)
    413{
    414    stq_he_p(ptr, le_bswap(v, 64));
    415}
    416
    417static inline int lduw_be_p(const void *ptr)
    418{
    419    return (uint16_t)be_bswap(lduw_he_p(ptr), 16);
    420}
    421
    422static inline int ldsw_be_p(const void *ptr)
    423{
    424    return (int16_t)be_bswap(lduw_he_p(ptr), 16);
    425}
    426
    427static inline int ldl_be_p(const void *ptr)
    428{
    429    return be_bswap(ldl_he_p(ptr), 32);
    430}
    431
    432static inline uint64_t ldq_be_p(const void *ptr)
    433{
    434    return be_bswap(ldq_he_p(ptr), 64);
    435}
    436
    437static inline void stw_be_p(void *ptr, uint16_t v)
    438{
    439    stw_he_p(ptr, be_bswap(v, 16));
    440}
    441
    442static inline void stl_be_p(void *ptr, uint32_t v)
    443{
    444    stl_he_p(ptr, be_bswap(v, 32));
    445}
    446
    447static inline void stq_be_p(void *ptr, uint64_t v)
    448{
    449    stq_he_p(ptr, be_bswap(v, 64));
    450}
    451
    452static inline unsigned long leul_to_cpu(unsigned long v)
    453{
    454#if HOST_LONG_BITS == 32
    455    return le_bswap(v, 32);
    456#elif HOST_LONG_BITS == 64
    457    return le_bswap(v, 64);
    458#else
    459# error Unknown sizeof long
    460#endif
    461}
    462
    463/* Store v to p as a sz byte value in host order */
    464#define DO_STN_LDN_P(END) \
    465    static inline void stn_## END ## _p(void *ptr, int sz, uint64_t v)  \
    466    {                                                                   \
    467        switch (sz) {                                                   \
    468        case 1:                                                         \
    469            stb_p(ptr, v);                                              \
    470            break;                                                      \
    471        case 2:                                                         \
    472            stw_ ## END ## _p(ptr, v);                                  \
    473            break;                                                      \
    474        case 4:                                                         \
    475            stl_ ## END ## _p(ptr, v);                                  \
    476            break;                                                      \
    477        case 8:                                                         \
    478            stq_ ## END ## _p(ptr, v);                                  \
    479            break;                                                      \
    480        default:                                                        \
    481            g_assert_not_reached();                                     \
    482        }                                                               \
    483    }                                                                   \
    484    static inline uint64_t ldn_## END ## _p(const void *ptr, int sz)    \
    485    {                                                                   \
    486        switch (sz) {                                                   \
    487        case 1:                                                         \
    488            return ldub_p(ptr);                                         \
    489        case 2:                                                         \
    490            return lduw_ ## END ## _p(ptr);                             \
    491        case 4:                                                         \
    492            return (uint32_t)ldl_ ## END ## _p(ptr);                    \
    493        case 8:                                                         \
    494            return ldq_ ## END ## _p(ptr);                              \
    495        default:                                                        \
    496            g_assert_not_reached();                                     \
    497        }                                                               \
    498    }
    499
    500DO_STN_LDN_P(he)
    501DO_STN_LDN_P(le)
    502DO_STN_LDN_P(be)
    503
    504#undef DO_STN_LDN_P
    505
    506#undef le_bswap
    507#undef be_bswap
    508#undef le_bswaps
    509#undef be_bswaps
    510
    511#ifdef __cplusplus
    512}
    513#endif
    514
    515#endif /* BSWAP_H */