X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=dma-helpers.c;h=2d7e02d35e57613b3921e5621829f3ba1a736bdc;hb=32e70aad7e984f7a609850985895e97fc03579ab;hp=53cbe925d155d9023ca5f876e13867836e1475d5;hpb=9474ab1487cc70140099c8500ae4a1947ca966c1;p=mirror_qemu.git diff --git a/dma-helpers.c b/dma-helpers.c index 53cbe925d1..2d7e02d35e 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -7,9 +7,10 @@ * (GNU GPL), version 2 or later. */ +#include "qemu/osdep.h" +#include "sysemu/block-backend.h" #include "sysemu/dma.h" -#include "trace.h" -#include "qemu/range.h" +#include "trace-root.h" #include "qemu/thread.h" #include "qemu/main-loop.h" @@ -27,7 +28,8 @@ int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len) memset(fillbuf, c, FILLBUF_SIZE); while (len > 0) { l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE; - error |= address_space_rw(as, addr, fillbuf, l, true); + error |= address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, + fillbuf, l, true); len -= l; addr += l; } @@ -67,21 +69,22 @@ void qemu_sglist_destroy(QEMUSGList *qsg) } typedef struct { - BlockDriverAIOCB common; - BlockDriverState *bs; - BlockDriverAIOCB *acb; + BlockAIOCB common; + AioContext *ctx; + BlockAIOCB *acb; QEMUSGList *sg; - uint64_t sector_num; + uint32_t align; + uint64_t offset; DMADirection dir; - bool in_cancel; int sg_cur_index; dma_addr_t sg_cur_byte; QEMUIOVector iov; QEMUBH *bh; DMAIOFunc *io_func; + void *io_func_opaque; } DMAAIOCB; -static void dma_bdrv_cb(void *opaque, int ret); +static void dma_blk_cb(void *opaque, int ret); static void reschedule_dma(void *opaque) { @@ -89,18 +92,10 @@ static void reschedule_dma(void *opaque) qemu_bh_delete(dbs->bh); dbs->bh = NULL; - dma_bdrv_cb(dbs, 0); + dma_blk_cb(dbs, 0); } -static void continue_after_map_failure(void *opaque) -{ - DMAAIOCB *dbs = (DMAAIOCB *)opaque; - - dbs->bh = qemu_bh_new(reschedule_dma, dbs); - qemu_bh_schedule(dbs->bh); -} - -static void dma_bdrv_unmap(DMAAIOCB *dbs) +static void dma_blk_unmap(DMAAIOCB *dbs) { int i; @@ -116,7 +111,7 @@ static void dma_complete(DMAAIOCB *dbs, int ret) { trace_dma_complete(dbs, ret, dbs->common.cb); - dma_bdrv_unmap(dbs); + dma_blk_unmap(dbs); if (dbs->common.cb) { dbs->common.cb(dbs->common.opaque, ret); } @@ -125,30 +120,25 @@ static void dma_complete(DMAAIOCB *dbs, int ret) qemu_bh_delete(dbs->bh); dbs->bh = NULL; } - if (!dbs->in_cancel) { - /* Requests may complete while dma_aio_cancel is in progress. In - * this case, the AIOCB should not be released because it is still - * referenced by dma_aio_cancel. */ - qemu_aio_release(dbs); - } + qemu_aio_unref(dbs); } -static void dma_bdrv_cb(void *opaque, int ret) +static void dma_blk_cb(void *opaque, int ret) { DMAAIOCB *dbs = (DMAAIOCB *)opaque; dma_addr_t cur_addr, cur_len; void *mem; - trace_dma_bdrv_cb(dbs, ret); + trace_dma_blk_cb(dbs, ret); dbs->acb = NULL; - dbs->sector_num += dbs->iov.size / 512; + dbs->offset += dbs->iov.size; if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) { dma_complete(dbs, ret); return; } - dma_bdrv_unmap(dbs); + dma_blk_unmap(dbs); while (dbs->sg_cur_index < dbs->sg->nsg) { cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte; @@ -166,76 +156,113 @@ static void dma_bdrv_cb(void *opaque, int ret) if (dbs->iov.size == 0) { trace_dma_map_wait(dbs); - cpu_register_map_client(dbs, continue_after_map_failure); + dbs->bh = aio_bh_new(dbs->ctx, reschedule_dma, dbs); + cpu_register_map_client(dbs->bh); return; } - dbs->acb = dbs->io_func(dbs->bs, dbs->sector_num, &dbs->iov, - dbs->iov.size / 512, dma_bdrv_cb, dbs); + if (!QEMU_IS_ALIGNED(dbs->iov.size, dbs->align)) { + qemu_iovec_discard_back(&dbs->iov, + QEMU_ALIGN_DOWN(dbs->iov.size, dbs->align)); + } + + aio_context_acquire(dbs->ctx); + dbs->acb = dbs->io_func(dbs->offset, &dbs->iov, + dma_blk_cb, dbs, dbs->io_func_opaque); + aio_context_release(dbs->ctx); assert(dbs->acb); } -static void dma_aio_cancel(BlockDriverAIOCB *acb) +static void dma_aio_cancel(BlockAIOCB *acb) { DMAAIOCB *dbs = container_of(acb, DMAAIOCB, common); trace_dma_aio_cancel(dbs); if (dbs->acb) { - BlockDriverAIOCB *acb = dbs->acb; - dbs->acb = NULL; - dbs->in_cancel = true; - bdrv_aio_cancel(acb); - dbs->in_cancel = false; + blk_aio_cancel_async(dbs->acb); + } + if (dbs->bh) { + cpu_unregister_map_client(dbs->bh); + qemu_bh_delete(dbs->bh); + dbs->bh = NULL; } - dbs->common.cb = NULL; - dma_complete(dbs, 0); +} + +static AioContext *dma_get_aio_context(BlockAIOCB *acb) +{ + DMAAIOCB *dbs = container_of(acb, DMAAIOCB, common); + + return dbs->ctx; } static const AIOCBInfo dma_aiocb_info = { .aiocb_size = sizeof(DMAAIOCB), - .cancel = dma_aio_cancel, + .cancel_async = dma_aio_cancel, + .get_aio_context = dma_get_aio_context, }; -BlockDriverAIOCB *dma_bdrv_io( - BlockDriverState *bs, QEMUSGList *sg, uint64_t sector_num, - DMAIOFunc *io_func, BlockDriverCompletionFunc *cb, +BlockAIOCB *dma_blk_io(AioContext *ctx, + QEMUSGList *sg, uint64_t offset, uint32_t align, + DMAIOFunc *io_func, void *io_func_opaque, + BlockCompletionFunc *cb, void *opaque, DMADirection dir) { - DMAAIOCB *dbs = qemu_aio_get(&dma_aiocb_info, bs, cb, opaque); + DMAAIOCB *dbs = qemu_aio_get(&dma_aiocb_info, NULL, cb, opaque); - trace_dma_bdrv_io(dbs, bs, sector_num, (dir == DMA_DIRECTION_TO_DEVICE)); + trace_dma_blk_io(dbs, io_func_opaque, offset, (dir == DMA_DIRECTION_TO_DEVICE)); dbs->acb = NULL; - dbs->bs = bs; dbs->sg = sg; - dbs->sector_num = sector_num; + dbs->ctx = ctx; + dbs->offset = offset; + dbs->align = align; dbs->sg_cur_index = 0; dbs->sg_cur_byte = 0; dbs->dir = dir; - dbs->in_cancel = false; dbs->io_func = io_func; + dbs->io_func_opaque = io_func_opaque; dbs->bh = NULL; qemu_iovec_init(&dbs->iov, sg->nsg); - dma_bdrv_cb(dbs, 0); + dma_blk_cb(dbs, 0); return &dbs->common; } -BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs, - QEMUSGList *sg, uint64_t sector, - void (*cb)(void *opaque, int ret), void *opaque) +static +BlockAIOCB *dma_blk_read_io_func(int64_t offset, QEMUIOVector *iov, + BlockCompletionFunc *cb, void *cb_opaque, + void *opaque) +{ + BlockBackend *blk = opaque; + return blk_aio_preadv(blk, offset, iov, 0, cb, cb_opaque); +} + +BlockAIOCB *dma_blk_read(BlockBackend *blk, + QEMUSGList *sg, uint64_t offset, uint32_t align, + void (*cb)(void *opaque, int ret), void *opaque) +{ + return dma_blk_io(blk_get_aio_context(blk), sg, offset, align, + dma_blk_read_io_func, blk, cb, opaque, + DMA_DIRECTION_FROM_DEVICE); +} + +static +BlockAIOCB *dma_blk_write_io_func(int64_t offset, QEMUIOVector *iov, + BlockCompletionFunc *cb, void *cb_opaque, + void *opaque) { - return dma_bdrv_io(bs, sg, sector, bdrv_aio_readv, cb, opaque, - DMA_DIRECTION_FROM_DEVICE); + BlockBackend *blk = opaque; + return blk_aio_pwritev(blk, offset, iov, 0, cb, cb_opaque); } -BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs, - QEMUSGList *sg, uint64_t sector, - void (*cb)(void *opaque, int ret), void *opaque) +BlockAIOCB *dma_blk_write(BlockBackend *blk, + QEMUSGList *sg, uint64_t offset, uint32_t align, + void (*cb)(void *opaque, int ret), void *opaque) { - return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque, - DMA_DIRECTION_TO_DEVICE); + return dma_blk_io(blk_get_aio_context(blk), sg, offset, align, + dma_blk_write_io_func, blk, cb, opaque, + DMA_DIRECTION_TO_DEVICE); } @@ -270,8 +297,8 @@ uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg) return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_TO_DEVICE); } -void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie, +void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, QEMUSGList *sg, enum BlockAcctType type) { - bdrv_acct_start(bs, cookie, sg->size, type); + block_acct_start(blk_get_stats(blk), cookie, sg->size, type); }