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

spapr_ovec.c (6080B)


      1/*
      2 * QEMU SPAPR Architecture Option Vector Helper Functions
      3 *
      4 * Copyright IBM Corp. 2016
      5 *
      6 * Authors:
      7 *  Bharata B Rao     <bharata@linux.vnet.ibm.com>
      8 *  Michael Roth      <mdroth@linux.vnet.ibm.com>
      9 *
     10 * This work is licensed under the terms of the GNU GPL, version 2 or later.
     11 * See the COPYING file in the top-level directory.
     12 */
     13
     14#include "qemu/osdep.h"
     15#include "hw/ppc/spapr_ovec.h"
     16#include "migration/vmstate.h"
     17#include "qemu/bitmap.h"
     18#include "exec/address-spaces.h"
     19#include "qemu/error-report.h"
     20#include "trace.h"
     21#include <libfdt.h>
     22
     23#define OV_MAXBYTES 256 /* not including length byte */
     24#define OV_MAXBITS (OV_MAXBYTES * BITS_PER_BYTE)
     25
     26/* we *could* work with bitmaps directly, but handling the bitmap privately
     27 * allows us to more safely make assumptions about the bitmap size and
     28 * simplify the calling code somewhat
     29 */
     30struct SpaprOptionVector {
     31    unsigned long *bitmap;
     32    int32_t bitmap_size; /* only used for migration */
     33};
     34
     35const VMStateDescription vmstate_spapr_ovec = {
     36    .name = "spapr_option_vector",
     37    .version_id = 1,
     38    .minimum_version_id = 1,
     39    .fields = (VMStateField[]) {
     40        VMSTATE_BITMAP(bitmap, SpaprOptionVector, 1, bitmap_size),
     41        VMSTATE_END_OF_LIST()
     42    }
     43};
     44
     45SpaprOptionVector *spapr_ovec_new(void)
     46{
     47    SpaprOptionVector *ov;
     48
     49    ov = g_new0(SpaprOptionVector, 1);
     50    ov->bitmap = bitmap_new(OV_MAXBITS);
     51    ov->bitmap_size = OV_MAXBITS;
     52
     53    return ov;
     54}
     55
     56SpaprOptionVector *spapr_ovec_clone(SpaprOptionVector *ov_orig)
     57{
     58    SpaprOptionVector *ov;
     59
     60    g_assert(ov_orig);
     61
     62    ov = spapr_ovec_new();
     63    bitmap_copy(ov->bitmap, ov_orig->bitmap, OV_MAXBITS);
     64
     65    return ov;
     66}
     67
     68void spapr_ovec_intersect(SpaprOptionVector *ov,
     69                          SpaprOptionVector *ov1,
     70                          SpaprOptionVector *ov2)
     71{
     72    g_assert(ov);
     73    g_assert(ov1);
     74    g_assert(ov2);
     75
     76    bitmap_and(ov->bitmap, ov1->bitmap, ov2->bitmap, OV_MAXBITS);
     77}
     78
     79/* returns true if ov1 has a subset of bits in ov2 */
     80bool spapr_ovec_subset(SpaprOptionVector *ov1, SpaprOptionVector *ov2)
     81{
     82    unsigned long *tmp = bitmap_new(OV_MAXBITS);
     83    bool result;
     84
     85    g_assert(ov1);
     86    g_assert(ov2);
     87
     88    bitmap_andnot(tmp, ov1->bitmap, ov2->bitmap, OV_MAXBITS);
     89    result = bitmap_empty(tmp, OV_MAXBITS);
     90
     91    g_free(tmp);
     92
     93    return result;
     94}
     95
     96void spapr_ovec_cleanup(SpaprOptionVector *ov)
     97{
     98    if (ov) {
     99        g_free(ov->bitmap);
    100        g_free(ov);
    101    }
    102}
    103
    104void spapr_ovec_set(SpaprOptionVector *ov, long bitnr)
    105{
    106    g_assert(ov);
    107    g_assert(bitnr < OV_MAXBITS);
    108
    109    set_bit(bitnr, ov->bitmap);
    110}
    111
    112void spapr_ovec_clear(SpaprOptionVector *ov, long bitnr)
    113{
    114    g_assert(ov);
    115    g_assert(bitnr < OV_MAXBITS);
    116
    117    clear_bit(bitnr, ov->bitmap);
    118}
    119
    120bool spapr_ovec_test(SpaprOptionVector *ov, long bitnr)
    121{
    122    g_assert(ov);
    123    g_assert(bitnr < OV_MAXBITS);
    124
    125    return test_bit(bitnr, ov->bitmap) ? true : false;
    126}
    127
    128bool spapr_ovec_empty(SpaprOptionVector *ov)
    129{
    130    g_assert(ov);
    131
    132    return bitmap_empty(ov->bitmap, OV_MAXBITS);
    133}
    134
    135static void guest_byte_to_bitmap(uint8_t entry, unsigned long *bitmap,
    136                                 long bitmap_offset)
    137{
    138    int i;
    139
    140    for (i = 0; i < BITS_PER_BYTE; i++) {
    141        if (entry & (1 << (BITS_PER_BYTE - 1 - i))) {
    142            bitmap_set(bitmap, bitmap_offset + i, 1);
    143        }
    144    }
    145}
    146
    147static uint8_t guest_byte_from_bitmap(unsigned long *bitmap, long bitmap_offset)
    148{
    149    uint8_t entry = 0;
    150    int i;
    151
    152    for (i = 0; i < BITS_PER_BYTE; i++) {
    153        if (test_bit(bitmap_offset + i, bitmap)) {
    154            entry |= (1 << (BITS_PER_BYTE - 1 - i));
    155        }
    156    }
    157
    158    return entry;
    159}
    160
    161static target_ulong vector_addr(target_ulong table_addr, int vector)
    162{
    163    uint16_t vector_count, vector_len;
    164    int i;
    165
    166    vector_count = ldub_phys(&address_space_memory, table_addr) + 1;
    167    if (vector > vector_count) {
    168        return 0;
    169    }
    170    table_addr++; /* skip nr option vectors */
    171
    172    for (i = 0; i < vector - 1; i++) {
    173        vector_len = ldub_phys(&address_space_memory, table_addr) + 1;
    174        table_addr += vector_len + 1; /* bit-vector + length byte */
    175    }
    176    return table_addr;
    177}
    178
    179SpaprOptionVector *spapr_ovec_parse_vector(target_ulong table_addr, int vector)
    180{
    181    SpaprOptionVector *ov;
    182    target_ulong addr;
    183    uint16_t vector_len;
    184    int i;
    185
    186    g_assert(table_addr);
    187    g_assert(vector >= 1);      /* vector numbering starts at 1 */
    188
    189    addr = vector_addr(table_addr, vector);
    190    if (!addr) {
    191        /* specified vector isn't present */
    192        return NULL;
    193    }
    194
    195    vector_len = ldub_phys(&address_space_memory, addr++) + 1;
    196    g_assert(vector_len <= OV_MAXBYTES);
    197    ov = spapr_ovec_new();
    198
    199    for (i = 0; i < vector_len; i++) {
    200        uint8_t entry = ldub_phys(&address_space_memory, addr + i);
    201        if (entry) {
    202            trace_spapr_ovec_parse_vector(vector, i + 1, vector_len, entry);
    203            guest_byte_to_bitmap(entry, ov->bitmap, i * BITS_PER_BYTE);
    204        }
    205    }
    206
    207    return ov;
    208}
    209
    210int spapr_dt_ovec(void *fdt, int fdt_offset,
    211                  SpaprOptionVector *ov, const char *name)
    212{
    213    uint8_t vec[OV_MAXBYTES + 1];
    214    uint16_t vec_len;
    215    unsigned long lastbit;
    216    int i;
    217
    218    g_assert(ov);
    219
    220    lastbit = find_last_bit(ov->bitmap, OV_MAXBITS);
    221    /* if no bits are set, include at least 1 byte of the vector so we can
    222     * still encoded this in the device tree while abiding by the same
    223     * encoding/sizing expected in ibm,client-architecture-support
    224     */
    225    vec_len = (lastbit == OV_MAXBITS) ? 1 : lastbit / BITS_PER_BYTE + 1;
    226    g_assert(vec_len <= OV_MAXBYTES);
    227    /* guest expects vector len encoded as vec_len - 1, since the length byte
    228     * is assumed and not included, and the first byte of the vector
    229     * is assumed as well
    230     */
    231    vec[0] = vec_len - 1;
    232
    233    for (i = 1; i < vec_len + 1; i++) {
    234        vec[i] = guest_byte_from_bitmap(ov->bitmap, (i - 1) * BITS_PER_BYTE);
    235        if (vec[i]) {
    236            trace_spapr_ovec_populate_dt(i, vec_len, vec[i]);
    237        }
    238    }
    239
    240    return fdt_setprop(fdt, fdt_offset, name, vec, vec_len + 1);
    241}