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

qed-table.c (5653B)


      1/*
      2 * QEMU Enhanced Disk Format Table I/O
      3 *
      4 * Copyright IBM, Corp. 2010
      5 *
      6 * Authors:
      7 *  Stefan Hajnoczi   <stefanha@linux.vnet.ibm.com>
      8 *  Anthony Liguori   <aliguori@us.ibm.com>
      9 *
     10 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
     11 * See the COPYING.LIB file in the top-level directory.
     12 *
     13 */
     14
     15#include "qemu/osdep.h"
     16#include "trace.h"
     17#include "qemu/sockets.h" /* for EINPROGRESS on Windows */
     18#include "qed.h"
     19#include "qemu/bswap.h"
     20
     21/* Called with table_lock held.  */
     22static int coroutine_fn qed_read_table(BDRVQEDState *s, uint64_t offset,
     23                                       QEDTable *table)
     24{
     25    unsigned int bytes = s->header.cluster_size * s->header.table_size;
     26
     27    int noffsets;
     28    int i, ret;
     29
     30    trace_qed_read_table(s, offset, table);
     31
     32    qemu_co_mutex_unlock(&s->table_lock);
     33    ret = bdrv_co_pread(s->bs->file, offset, bytes, table->offsets, 0);
     34    qemu_co_mutex_lock(&s->table_lock);
     35    if (ret < 0) {
     36        goto out;
     37    }
     38
     39    /* Byteswap offsets */
     40    noffsets = bytes / sizeof(uint64_t);
     41    for (i = 0; i < noffsets; i++) {
     42        table->offsets[i] = le64_to_cpu(table->offsets[i]);
     43    }
     44
     45    ret = 0;
     46out:
     47    /* Completion */
     48    trace_qed_read_table_cb(s, table, ret);
     49    return ret;
     50}
     51
     52/**
     53 * Write out an updated part or all of a table
     54 *
     55 * @s:          QED state
     56 * @offset:     Offset of table in image file, in bytes
     57 * @table:      Table
     58 * @index:      Index of first element
     59 * @n:          Number of elements
     60 * @flush:      Whether or not to sync to disk
     61 *
     62 * Called with table_lock held.
     63 */
     64static int coroutine_fn qed_write_table(BDRVQEDState *s, uint64_t offset,
     65                                        QEDTable *table, unsigned int index,
     66                                        unsigned int n, bool flush)
     67{
     68    unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1;
     69    unsigned int start, end, i;
     70    QEDTable *new_table;
     71    size_t len_bytes;
     72    int ret;
     73
     74    trace_qed_write_table(s, offset, table, index, n);
     75
     76    /* Calculate indices of the first and one after last elements */
     77    start = index & ~sector_mask;
     78    end = (index + n + sector_mask) & ~sector_mask;
     79
     80    len_bytes = (end - start) * sizeof(uint64_t);
     81
     82    new_table = qemu_blockalign(s->bs, len_bytes);
     83
     84    /* Byteswap table */
     85    for (i = start; i < end; i++) {
     86        uint64_t le_offset = cpu_to_le64(table->offsets[i]);
     87        new_table->offsets[i - start] = le_offset;
     88    }
     89
     90    /* Adjust for offset into table */
     91    offset += start * sizeof(uint64_t);
     92
     93    qemu_co_mutex_unlock(&s->table_lock);
     94    ret = bdrv_co_pwrite(s->bs->file, offset, len_bytes, new_table->offsets, 0);
     95    qemu_co_mutex_lock(&s->table_lock);
     96    trace_qed_write_table_cb(s, table, flush, ret);
     97    if (ret < 0) {
     98        goto out;
     99    }
    100
    101    if (flush) {
    102        ret = bdrv_flush(s->bs);
    103        if (ret < 0) {
    104            goto out;
    105        }
    106    }
    107
    108    ret = 0;
    109out:
    110    qemu_vfree(new_table);
    111    return ret;
    112}
    113
    114int coroutine_fn qed_read_l1_table_sync(BDRVQEDState *s)
    115{
    116    return qed_read_table(s, s->header.l1_table_offset, s->l1_table);
    117}
    118
    119/* Called with table_lock held.  */
    120int coroutine_fn qed_write_l1_table(BDRVQEDState *s, unsigned int index,
    121                                    unsigned int n)
    122{
    123    BLKDBG_EVENT(s->bs->file, BLKDBG_L1_UPDATE);
    124    return qed_write_table(s, s->header.l1_table_offset,
    125                           s->l1_table, index, n, false);
    126}
    127
    128int coroutine_fn qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
    129                                         unsigned int n)
    130{
    131    return qed_write_l1_table(s, index, n);
    132}
    133
    134/* Called with table_lock held.  */
    135int coroutine_fn qed_read_l2_table(BDRVQEDState *s, QEDRequest *request,
    136                                   uint64_t offset)
    137{
    138    int ret;
    139
    140    qed_unref_l2_cache_entry(request->l2_table);
    141
    142    /* Check for cached L2 entry */
    143    request->l2_table = qed_find_l2_cache_entry(&s->l2_cache, offset);
    144    if (request->l2_table) {
    145        return 0;
    146    }
    147
    148    request->l2_table = qed_alloc_l2_cache_entry(&s->l2_cache);
    149    request->l2_table->table = qed_alloc_table(s);
    150
    151    BLKDBG_EVENT(s->bs->file, BLKDBG_L2_LOAD);
    152    ret = qed_read_table(s, offset, request->l2_table->table);
    153
    154    if (ret) {
    155        /* can't trust loaded L2 table anymore */
    156        qed_unref_l2_cache_entry(request->l2_table);
    157        request->l2_table = NULL;
    158    } else {
    159        request->l2_table->offset = offset;
    160
    161        qed_commit_l2_cache_entry(&s->l2_cache, request->l2_table);
    162
    163        /* This is guaranteed to succeed because we just committed the entry
    164         * to the cache.
    165         */
    166        request->l2_table = qed_find_l2_cache_entry(&s->l2_cache, offset);
    167        assert(request->l2_table != NULL);
    168    }
    169
    170    return ret;
    171}
    172
    173int coroutine_fn qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
    174                                        uint64_t offset)
    175{
    176    return qed_read_l2_table(s, request, offset);
    177}
    178
    179/* Called with table_lock held.  */
    180int coroutine_fn qed_write_l2_table(BDRVQEDState *s, QEDRequest *request,
    181                                    unsigned int index, unsigned int n,
    182                                    bool flush)
    183{
    184    BLKDBG_EVENT(s->bs->file, BLKDBG_L2_UPDATE);
    185    return qed_write_table(s, request->l2_table->offset,
    186                           request->l2_table->table, index, n, flush);
    187}
    188
    189int coroutine_fn qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
    190                                         unsigned int index, unsigned int n,
    191                                         bool flush)
    192{
    193    return qed_write_l2_table(s, request, index, n, flush);
    194}