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

block.c (7233B)


      1/*
      2 * Common code for block device models
      3 *
      4 * Copyright (C) 2012 Red Hat, Inc.
      5 *
      6 * This work is licensed under the terms of the GNU GPL, version 2 or
      7 * later.  See the COPYING file in the top-level directory.
      8 */
      9
     10#include "qemu/osdep.h"
     11#include "sysemu/blockdev.h"
     12#include "sysemu/block-backend.h"
     13#include "hw/block/block.h"
     14#include "qapi/error.h"
     15#include "qapi/qapi-types-block.h"
     16
     17/*
     18 * Read the entire contents of @blk into @buf.
     19 * @blk's contents must be @size bytes, and @size must be at most
     20 * BDRV_REQUEST_MAX_BYTES.
     21 * On success, return true.
     22 * On failure, store an error through @errp and return false.
     23 * Note that the error messages do not identify the block backend.
     24 * TODO Since callers don't either, this can result in confusing
     25 * errors.
     26 * This function not intended for actual block devices, which read on
     27 * demand.  It's for things like memory devices that (ab)use a block
     28 * backend to provide persistence.
     29 */
     30bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size,
     31                                 Error **errp)
     32{
     33    int64_t blk_len;
     34    int ret;
     35
     36    blk_len = blk_getlength(blk);
     37    if (blk_len < 0) {
     38        error_setg_errno(errp, -blk_len,
     39                         "can't get size of block backend");
     40        return false;
     41    }
     42    if (blk_len != size) {
     43        error_setg(errp, "device requires %" HWADDR_PRIu " bytes, "
     44                   "block backend provides %" PRIu64 " bytes",
     45                   size, blk_len);
     46        return false;
     47    }
     48
     49    /*
     50     * We could loop for @size > BDRV_REQUEST_MAX_BYTES, but if we
     51     * ever get to the point we want to read *gigabytes* here, we
     52     * should probably rework the device to be more like an actual
     53     * block device and read only on demand.
     54     */
     55    assert(size <= BDRV_REQUEST_MAX_BYTES);
     56    ret = blk_pread(blk, 0, buf, size);
     57    if (ret < 0) {
     58        error_setg_errno(errp, -ret, "can't read block backend");
     59        return false;
     60    }
     61    return true;
     62}
     63
     64bool blkconf_blocksizes(BlockConf *conf, Error **errp)
     65{
     66    BlockBackend *blk = conf->blk;
     67    BlockSizes blocksizes;
     68    BlockDriverState *bs;
     69    bool use_blocksizes;
     70    bool use_bs;
     71
     72    switch (conf->backend_defaults) {
     73    case ON_OFF_AUTO_AUTO:
     74        use_blocksizes = !blk_probe_blocksizes(blk, &blocksizes);
     75        use_bs = false;
     76        break;
     77
     78    case ON_OFF_AUTO_ON:
     79        use_blocksizes = !blk_probe_blocksizes(blk, &blocksizes);
     80        bs = blk_bs(blk);
     81        use_bs = bs;
     82        break;
     83
     84    case ON_OFF_AUTO_OFF:
     85        use_blocksizes = false;
     86        use_bs = false;
     87        break;
     88
     89    default:
     90        abort();
     91    }
     92
     93    /* fill in detected values if they are not defined via qemu command line */
     94    if (!conf->physical_block_size) {
     95        if (use_blocksizes) {
     96           conf->physical_block_size = blocksizes.phys;
     97        } else {
     98            conf->physical_block_size = BDRV_SECTOR_SIZE;
     99        }
    100    }
    101    if (!conf->logical_block_size) {
    102        if (use_blocksizes) {
    103            conf->logical_block_size = blocksizes.log;
    104        } else {
    105            conf->logical_block_size = BDRV_SECTOR_SIZE;
    106        }
    107    }
    108    if (use_bs) {
    109        if (!conf->opt_io_size) {
    110            conf->opt_io_size = bs->bl.opt_transfer;
    111        }
    112        if (conf->discard_granularity == -1) {
    113            if (bs->bl.pdiscard_alignment) {
    114                conf->discard_granularity = bs->bl.pdiscard_alignment;
    115            } else if (bs->bl.request_alignment != 1) {
    116                conf->discard_granularity = bs->bl.request_alignment;
    117            }
    118        }
    119    }
    120
    121    if (conf->logical_block_size > conf->physical_block_size) {
    122        error_setg(errp,
    123                   "logical_block_size > physical_block_size not supported");
    124        return false;
    125    }
    126
    127    if (!QEMU_IS_ALIGNED(conf->min_io_size, conf->logical_block_size)) {
    128        error_setg(errp,
    129                   "min_io_size must be a multiple of logical_block_size");
    130        return false;
    131    }
    132
    133    /*
    134     * all devices which support min_io_size (scsi and virtio-blk) expose it to
    135     * the guest as a uint16_t in units of logical blocks
    136     */
    137    if (conf->min_io_size / conf->logical_block_size > UINT16_MAX) {
    138        error_setg(errp, "min_io_size must not exceed %u logical blocks",
    139                   UINT16_MAX);
    140        return false;
    141    }
    142
    143    if (!QEMU_IS_ALIGNED(conf->opt_io_size, conf->logical_block_size)) {
    144        error_setg(errp,
    145                   "opt_io_size must be a multiple of logical_block_size");
    146        return false;
    147    }
    148
    149    if (conf->discard_granularity != -1 &&
    150        !QEMU_IS_ALIGNED(conf->discard_granularity,
    151                         conf->logical_block_size)) {
    152        error_setg(errp, "discard_granularity must be "
    153                   "a multiple of logical_block_size");
    154        return false;
    155    }
    156
    157    return true;
    158}
    159
    160bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
    161                                   bool resizable, Error **errp)
    162{
    163    BlockBackend *blk = conf->blk;
    164    BlockdevOnError rerror, werror;
    165    uint64_t perm, shared_perm;
    166    bool wce;
    167    int ret;
    168
    169    perm = BLK_PERM_CONSISTENT_READ;
    170    if (!readonly) {
    171        perm |= BLK_PERM_WRITE;
    172    }
    173
    174    shared_perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
    175                  BLK_PERM_GRAPH_MOD;
    176    if (resizable) {
    177        shared_perm |= BLK_PERM_RESIZE;
    178    }
    179    if (conf->share_rw) {
    180        shared_perm |= BLK_PERM_WRITE;
    181    }
    182
    183    ret = blk_set_perm(blk, perm, shared_perm, errp);
    184    if (ret < 0) {
    185        return false;
    186    }
    187
    188    switch (conf->wce) {
    189    case ON_OFF_AUTO_ON:    wce = true; break;
    190    case ON_OFF_AUTO_OFF:   wce = false; break;
    191    case ON_OFF_AUTO_AUTO:  wce = blk_enable_write_cache(blk); break;
    192    default:
    193        abort();
    194    }
    195
    196    rerror = conf->rerror;
    197    if (rerror == BLOCKDEV_ON_ERROR_AUTO) {
    198        rerror = blk_get_on_error(blk, true);
    199    }
    200
    201    werror = conf->werror;
    202    if (werror == BLOCKDEV_ON_ERROR_AUTO) {
    203        werror = blk_get_on_error(blk, false);
    204    }
    205
    206    blk_set_enable_write_cache(blk, wce);
    207    blk_set_on_error(blk, rerror, werror);
    208
    209    return true;
    210}
    211
    212bool blkconf_geometry(BlockConf *conf, int *ptrans,
    213                      unsigned cyls_max, unsigned heads_max, unsigned secs_max,
    214                      Error **errp)
    215{
    216    if (!conf->cyls && !conf->heads && !conf->secs) {
    217        hd_geometry_guess(conf->blk,
    218                          &conf->cyls, &conf->heads, &conf->secs,
    219                          ptrans);
    220    } else if (ptrans && *ptrans == BIOS_ATA_TRANSLATION_AUTO) {
    221        *ptrans = hd_bios_chs_auto_trans(conf->cyls, conf->heads, conf->secs);
    222    }
    223    if (conf->cyls || conf->heads || conf->secs) {
    224        if (conf->cyls < 1 || conf->cyls > cyls_max) {
    225            error_setg(errp, "cyls must be between 1 and %u", cyls_max);
    226            return false;
    227        }
    228        if (conf->heads < 1 || conf->heads > heads_max) {
    229            error_setg(errp, "heads must be between 1 and %u", heads_max);
    230            return false;
    231        }
    232        if (conf->secs < 1 || conf->secs > secs_max) {
    233            error_setg(errp, "secs must be between 1 and %u", secs_max);
    234            return false;
    235        }
    236    }
    237    return true;
    238}