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

blkreplay.c (4548B)


      1/*
      2 * Block protocol for record/replay
      3 *
      4 * Copyright (c) 2010-2016 Institute for System Programming
      5 *                         of the Russian Academy of Sciences.
      6 *
      7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
      8 * See the COPYING file in the top-level directory.
      9 *
     10 */
     11
     12#include "qemu/osdep.h"
     13#include "qemu/module.h"
     14#include "block/block_int.h"
     15#include "sysemu/replay.h"
     16#include "qapi/error.h"
     17
     18typedef struct Request {
     19    Coroutine *co;
     20    QEMUBH *bh;
     21} Request;
     22
     23static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
     24                          Error **errp)
     25{
     26    int ret;
     27
     28    /* Open the image file */
     29    bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds,
     30                               BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
     31                               false, errp);
     32    if (!bs->file) {
     33        ret = -EINVAL;
     34        goto fail;
     35    }
     36
     37    bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
     38    bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED;
     39
     40    ret = 0;
     41fail:
     42    return ret;
     43}
     44
     45static int64_t blkreplay_getlength(BlockDriverState *bs)
     46{
     47    return bdrv_getlength(bs->file->bs);
     48}
     49
     50/* This bh is used for synchronization of return from coroutines.
     51   It continues yielded coroutine which then finishes its execution.
     52   BH is called adjusted to some replay checkpoint, therefore
     53   record and replay will always finish coroutines deterministically.
     54*/
     55static void blkreplay_bh_cb(void *opaque)
     56{
     57    Request *req = opaque;
     58    aio_co_wake(req->co);
     59    qemu_bh_delete(req->bh);
     60    g_free(req);
     61}
     62
     63static void block_request_create(uint64_t reqid, BlockDriverState *bs,
     64                                 Coroutine *co)
     65{
     66    Request *req = g_new(Request, 1);
     67    *req = (Request) {
     68        .co = co,
     69        .bh = aio_bh_new(bdrv_get_aio_context(bs), blkreplay_bh_cb, req),
     70    };
     71    replay_block_event(req->bh, reqid);
     72}
     73
     74static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
     75    int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
     76{
     77    uint64_t reqid = blkreplay_next_id();
     78    int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
     79    block_request_create(reqid, bs, qemu_coroutine_self());
     80    qemu_coroutine_yield();
     81
     82    return ret;
     83}
     84
     85static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
     86    int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
     87{
     88    uint64_t reqid = blkreplay_next_id();
     89    int ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
     90    block_request_create(reqid, bs, qemu_coroutine_self());
     91    qemu_coroutine_yield();
     92
     93    return ret;
     94}
     95
     96static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
     97    int64_t offset, int64_t bytes, BdrvRequestFlags flags)
     98{
     99    uint64_t reqid = blkreplay_next_id();
    100    int ret = bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
    101    block_request_create(reqid, bs, qemu_coroutine_self());
    102    qemu_coroutine_yield();
    103
    104    return ret;
    105}
    106
    107static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs,
    108                                              int64_t offset, int64_t bytes)
    109{
    110    uint64_t reqid = blkreplay_next_id();
    111    int ret = bdrv_co_pdiscard(bs->file, offset, bytes);
    112    block_request_create(reqid, bs, qemu_coroutine_self());
    113    qemu_coroutine_yield();
    114
    115    return ret;
    116}
    117
    118static int coroutine_fn blkreplay_co_flush(BlockDriverState *bs)
    119{
    120    uint64_t reqid = blkreplay_next_id();
    121    int ret = bdrv_co_flush(bs->file->bs);
    122    block_request_create(reqid, bs, qemu_coroutine_self());
    123    qemu_coroutine_yield();
    124
    125    return ret;
    126}
    127
    128static int blkreplay_snapshot_goto(BlockDriverState *bs,
    129                                   const char *snapshot_id)
    130{
    131    return bdrv_snapshot_goto(bs->file->bs, snapshot_id, NULL);
    132}
    133
    134static BlockDriver bdrv_blkreplay = {
    135    .format_name            = "blkreplay",
    136    .instance_size          = 0,
    137    .is_filter              = true,
    138
    139    .bdrv_open              = blkreplay_open,
    140    .bdrv_child_perm        = bdrv_default_perms,
    141    .bdrv_getlength         = blkreplay_getlength,
    142
    143    .bdrv_co_preadv         = blkreplay_co_preadv,
    144    .bdrv_co_pwritev        = blkreplay_co_pwritev,
    145
    146    .bdrv_co_pwrite_zeroes  = blkreplay_co_pwrite_zeroes,
    147    .bdrv_co_pdiscard       = blkreplay_co_pdiscard,
    148    .bdrv_co_flush          = blkreplay_co_flush,
    149
    150    .bdrv_snapshot_goto     = blkreplay_snapshot_goto,
    151};
    152
    153static void bdrv_blkreplay_init(void)
    154{
    155    bdrv_register(&bdrv_blkreplay);
    156}
    157
    158block_init(bdrv_blkreplay_init);