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

rocker_tlv.h (7331B)


      1/*
      2 * QEMU rocker switch emulation - TLV parsing and composing
      3 *
      4 * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
      5 *
      6 * This program is free software; you can redistribute it and/or modify
      7 * it under the terms of the GNU General Public License as published by
      8 * the Free Software Foundation; either version 2 of the License, or
      9 * (at your option) any later version.
     10 *
     11 * This program is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     14 * GNU General Public License for more details.
     15 */
     16
     17#ifndef ROCKER_TLV_H
     18#define ROCKER_TLV_H
     19
     20#define ROCKER_TLV_ALIGNTO 8U
     21#define ROCKER_TLV_ALIGN(len) \
     22    (((len) + ROCKER_TLV_ALIGNTO - 1) & ~(ROCKER_TLV_ALIGNTO - 1))
     23#define ROCKER_TLV_HDRLEN ROCKER_TLV_ALIGN(sizeof(RockerTlv))
     24
     25/*
     26 *  <------- ROCKER_TLV_HDRLEN -------> <--- ROCKER_TLV_ALIGN(payload) --->
     27 * +-----------------------------+- - -+- - - - - - - - - - - - - - -+- - -+
     28 * |             Header          | Pad |           Payload           | Pad |
     29 * |          (RockerTlv)        | ing |                             | ing |
     30 * +-----------------------------+- - -+- - - - - - - - - - - - - - -+- - -+
     31 *  <--------------------------- tlv->len -------------------------->
     32 */
     33
     34static inline RockerTlv *rocker_tlv_next(const RockerTlv *tlv, int *remaining)
     35{
     36    int totlen = ROCKER_TLV_ALIGN(le16_to_cpu(tlv->len));
     37
     38    *remaining -= totlen;
     39    return (RockerTlv *) ((char *) tlv + totlen);
     40}
     41
     42static inline int rocker_tlv_ok(const RockerTlv *tlv, int remaining)
     43{
     44    return remaining >= (int) ROCKER_TLV_HDRLEN &&
     45           le16_to_cpu(tlv->len) >= ROCKER_TLV_HDRLEN &&
     46           le16_to_cpu(tlv->len) <= remaining;
     47}
     48
     49#define rocker_tlv_for_each(pos, head, len, rem) \
     50    for (pos = head, rem = len; \
     51         rocker_tlv_ok(pos, rem); \
     52         pos = rocker_tlv_next(pos, &(rem)))
     53
     54#define rocker_tlv_for_each_nested(pos, tlv, rem) \
     55        rocker_tlv_for_each(pos, rocker_tlv_data(tlv), rocker_tlv_len(tlv), rem)
     56
     57static inline int rocker_tlv_size(int payload)
     58{
     59    return ROCKER_TLV_HDRLEN + payload;
     60}
     61
     62static inline int rocker_tlv_total_size(int payload)
     63{
     64    return ROCKER_TLV_ALIGN(rocker_tlv_size(payload));
     65}
     66
     67static inline int rocker_tlv_padlen(int payload)
     68{
     69    return rocker_tlv_total_size(payload) - rocker_tlv_size(payload);
     70}
     71
     72static inline int rocker_tlv_type(const RockerTlv *tlv)
     73{
     74    return le32_to_cpu(tlv->type);
     75}
     76
     77static inline void *rocker_tlv_data(const RockerTlv *tlv)
     78{
     79    return (char *) tlv + ROCKER_TLV_HDRLEN;
     80}
     81
     82static inline int rocker_tlv_len(const RockerTlv *tlv)
     83{
     84    return le16_to_cpu(tlv->len) - ROCKER_TLV_HDRLEN;
     85}
     86
     87static inline uint8_t rocker_tlv_get_u8(const RockerTlv *tlv)
     88{
     89    return *(uint8_t *) rocker_tlv_data(tlv);
     90}
     91
     92static inline uint16_t rocker_tlv_get_u16(const RockerTlv *tlv)
     93{
     94    return *(uint16_t *) rocker_tlv_data(tlv);
     95}
     96
     97static inline uint32_t rocker_tlv_get_u32(const RockerTlv *tlv)
     98{
     99    return *(uint32_t *) rocker_tlv_data(tlv);
    100}
    101
    102static inline uint64_t rocker_tlv_get_u64(const RockerTlv *tlv)
    103{
    104    return *(uint64_t *) rocker_tlv_data(tlv);
    105}
    106
    107static inline uint16_t rocker_tlv_get_le16(const RockerTlv *tlv)
    108{
    109    return lduw_le_p(rocker_tlv_data(tlv));
    110}
    111
    112static inline uint32_t rocker_tlv_get_le32(const RockerTlv *tlv)
    113{
    114    return ldl_le_p(rocker_tlv_data(tlv));
    115}
    116
    117static inline uint64_t rocker_tlv_get_le64(const RockerTlv *tlv)
    118{
    119    return ldq_le_p(rocker_tlv_data(tlv));
    120}
    121
    122static inline void rocker_tlv_parse(RockerTlv **tb, int maxtype,
    123                                    const char *buf, int buf_len)
    124{
    125    const RockerTlv *tlv;
    126    const RockerTlv *head = (const RockerTlv *) buf;
    127    int rem;
    128
    129    memset(tb, 0, sizeof(RockerTlv *) * (maxtype + 1));
    130
    131    rocker_tlv_for_each(tlv, head, buf_len, rem) {
    132        uint32_t type = rocker_tlv_type(tlv);
    133
    134        if (type > 0 && type <= maxtype) {
    135            tb[type] = (RockerTlv *) tlv;
    136        }
    137    }
    138}
    139
    140static inline void rocker_tlv_parse_nested(RockerTlv **tb, int maxtype,
    141                                           const RockerTlv *tlv)
    142{
    143    rocker_tlv_parse(tb, maxtype, rocker_tlv_data(tlv), rocker_tlv_len(tlv));
    144}
    145
    146static inline RockerTlv *rocker_tlv_start(char *buf, int buf_pos)
    147{
    148    return (RockerTlv *) (buf + buf_pos);
    149}
    150
    151static inline void rocker_tlv_put_iov(char *buf, int *buf_pos,
    152                                      int type, const struct iovec *iov,
    153                                      const unsigned int iovcnt)
    154{
    155    size_t len = iov_size(iov, iovcnt);
    156    int total_size = rocker_tlv_total_size(len);
    157    RockerTlv *tlv;
    158
    159    tlv = rocker_tlv_start(buf, *buf_pos);
    160    *buf_pos += total_size;
    161    tlv->type = cpu_to_le32(type);
    162    tlv->len = cpu_to_le16(rocker_tlv_size(len));
    163    iov_to_buf(iov, iovcnt, 0, rocker_tlv_data(tlv), len);
    164    memset((char *) tlv + le16_to_cpu(tlv->len), 0, rocker_tlv_padlen(len));
    165}
    166
    167static inline void rocker_tlv_put(char *buf, int *buf_pos,
    168                                  int type, int len, void *data)
    169{
    170    struct iovec iov = {
    171        .iov_base = data,
    172        .iov_len = len,
    173    };
    174
    175    rocker_tlv_put_iov(buf, buf_pos, type, &iov, 1);
    176}
    177
    178static inline void rocker_tlv_put_u8(char *buf, int *buf_pos,
    179                                     int type, uint8_t value)
    180{
    181    rocker_tlv_put(buf, buf_pos, type, sizeof(uint8_t), &value);
    182}
    183
    184static inline void rocker_tlv_put_u16(char *buf, int *buf_pos,
    185                                      int type, uint16_t value)
    186{
    187    rocker_tlv_put(buf, buf_pos, type, sizeof(uint16_t), &value);
    188}
    189
    190static inline void rocker_tlv_put_u32(char *buf, int *buf_pos,
    191                                      int type, uint32_t value)
    192{
    193    rocker_tlv_put(buf, buf_pos, type, sizeof(uint32_t), &value);
    194}
    195
    196static inline void rocker_tlv_put_u64(char *buf, int *buf_pos,
    197                                      int type, uint64_t value)
    198{
    199    rocker_tlv_put(buf, buf_pos, type, sizeof(uint64_t), &value);
    200}
    201
    202static inline void rocker_tlv_put_le16(char *buf, int *buf_pos,
    203                                       int type, uint16_t value)
    204{
    205    value = cpu_to_le16(value);
    206    rocker_tlv_put(buf, buf_pos, type, sizeof(uint16_t), &value);
    207}
    208
    209static inline void rocker_tlv_put_le32(char *buf, int *buf_pos,
    210                                       int type, uint32_t value)
    211{
    212    value = cpu_to_le32(value);
    213    rocker_tlv_put(buf, buf_pos, type, sizeof(uint32_t), &value);
    214}
    215
    216static inline void rocker_tlv_put_le64(char *buf, int *buf_pos,
    217                                       int type, uint64_t value)
    218{
    219    value = cpu_to_le64(value);
    220    rocker_tlv_put(buf, buf_pos, type, sizeof(uint64_t), &value);
    221}
    222
    223static inline RockerTlv *rocker_tlv_nest_start(char *buf, int *buf_pos,
    224                                               int type)
    225{
    226    RockerTlv *start = rocker_tlv_start(buf, *buf_pos);
    227
    228    rocker_tlv_put(buf, buf_pos, type, 0, NULL);
    229    return start;
    230}
    231
    232static inline void rocker_tlv_nest_end(char *buf, int *buf_pos,
    233                                       RockerTlv *start)
    234{
    235    start->len = (char *) rocker_tlv_start(buf, *buf_pos) - (char *) start;
    236}
    237
    238static inline void rocker_tlv_nest_cancel(char *buf, int *buf_pos,
    239                                          RockerTlv *start)
    240{
    241    *buf_pos = (char *) start - buf;
    242}
    243
    244#endif