From patchwork Fri Feb 27 13:11:25 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Dovgalyuk X-Patchwork-Id: 444277 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id ECF0F1400B6 for ; Sat, 28 Feb 2015 00:21:05 +1100 (AEDT) Received: from localhost ([::1]:35733 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YRKql-0000V9-SG for incoming@patchwork.ozlabs.org; Fri, 27 Feb 2015 08:21:03 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53771) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YRKhQ-0002Ts-57 for qemu-devel@nongnu.org; Fri, 27 Feb 2015 08:11:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YRKhO-0005N3-5y for qemu-devel@nongnu.org; Fri, 27 Feb 2015 08:11:24 -0500 Received: from mail.ispras.ru ([83.149.199.45]:34703) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YRKhN-0005Mr-QI for qemu-devel@nongnu.org; Fri, 27 Feb 2015 08:11:22 -0500 Received: from [10.10.150.93] (unknown [85.142.117.224]) by mail.ispras.ru (Postfix) with ESMTPSA id 0FCD354006F; Fri, 27 Feb 2015 16:11:21 +0300 (MSK) To: qemu-devel@nongnu.org From: Pavel Dovgalyuk Date: Fri, 27 Feb 2015 16:11:25 +0300 Message-ID: <20150227131125.11912.61091.stgit@PASHA-ISP> In-Reply-To: <20150227130939.11912.50660.stgit@PASHA-ISP> References: <20150227130939.11912.50660.stgit@PASHA-ISP> User-Agent: StGit/0.16 MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 83.149.199.45 Cc: peter.maydell@linaro.org, peter.crosthwaite@xilinx.com, alex.bennee@linaro.org, mark.burton@greensocs.com, real@ispras.ru, batuzovk@ispras.ru, maria.klimushenkova@ispras.ru, pavel.dovgaluk@ispras.ru, pbonzini@redhat.com, afaerber@suse.de, fred.konrad@greensocs.com Subject: [Qemu-devel] [RFC PATCH v10 17/24] replay: bottom halves X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch introduces bottom half event for replay queue. It saves the events into the queue and process them at the checkpoints and instructions execution. Signed-off-by: Pavel Dovgalyuk --- async.c | 24 +++++++++++++++++++++++- dma-helpers.c | 4 +++- hw/ide/ahci.c | 4 +++- hw/ide/core.c | 4 +++- hw/timer/arm_timer.c | 2 +- hw/usb/hcd-uhci.c | 2 +- include/block/aio.h | 18 ++++++++++++++++++ include/qemu/main-loop.h | 1 + main-loop.c | 5 +++++ replay/replay-events.c | 16 ++++++++++++++++ replay/replay-internal.h | 1 + replay/replay.h | 2 ++ stubs/replay.c | 4 ++++ 13 files changed, 81 insertions(+), 6 deletions(-) diff --git a/async.c b/async.c index d83b7c8..75368af 100644 --- a/async.c +++ b/async.c @@ -27,6 +27,7 @@ #include "block/thread-pool.h" #include "qemu/main-loop.h" #include "qemu/atomic.h" +#include "replay/replay.h" /***********************************************************/ /* bottom halves (can be seen as timers which expire ASAP) */ @@ -39,6 +40,8 @@ struct QEMUBH { bool scheduled; bool idle; bool deleted; + bool replay; + uint64_t id; }; QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque) @@ -56,6 +59,21 @@ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque) return bh; } +QEMUBH *aio_bh_new_replay(AioContext *ctx, QEMUBHFunc *cb, void *opaque, + uint64_t id) +{ + QEMUBH *bh = aio_bh_new(ctx, cb, opaque); + bh->replay = true; + bh->id = id; + return bh; +} + +void aio_bh_call(void *opaque) +{ + QEMUBH *bh = (QEMUBH *)opaque; + bh->cb(bh->opaque); +} + /* Multiple occurrences of aio_bh_poll cannot be called concurrently */ int aio_bh_poll(AioContext *ctx) { @@ -77,7 +95,11 @@ int aio_bh_poll(AioContext *ctx) if (!bh->idle) ret = 1; bh->idle = 0; - bh->cb(bh->opaque); + if (!bh->replay) { + aio_bh_call(bh); + } else { + replay_add_bh_event(bh, bh->id); + } } } diff --git a/dma-helpers.c b/dma-helpers.c index 6918572..357d7e9 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -13,6 +13,7 @@ #include "qemu/range.h" #include "qemu/thread.h" #include "qemu/main-loop.h" +#include "replay/replay.h" /* #define DEBUG_IOMMU */ @@ -96,7 +97,8 @@ static void continue_after_map_failure(void *opaque) { DMAAIOCB *dbs = (DMAAIOCB *)opaque; - dbs->bh = qemu_bh_new(reschedule_dma, dbs); + dbs->bh = qemu_bh_new_replay(reschedule_dma, dbs, + replay_get_current_step()); qemu_bh_schedule(dbs->bh); } diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 5651372..13d7f84 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -33,6 +33,7 @@ #include "internal.h" #include #include +#include "replay/replay.h" #define DEBUG_AHCI 0 @@ -1243,7 +1244,8 @@ static void ahci_cmd_done(IDEDMA *dma) if (!ad->check_bh) { /* maybe we still have something to process, check later */ - ad->check_bh = qemu_bh_new(ahci_check_cmd_bh, ad); + ad->check_bh = qemu_bh_new_replay(ahci_check_cmd_bh, ad, + replay_get_current_step()); qemu_bh_schedule(ad->check_bh); } } diff --git a/hw/ide/core.c b/hw/ide/core.c index ac3f015..d6af700 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -32,6 +32,7 @@ #include "sysemu/dma.h" #include "hw/block/block.h" #include "sysemu/block-backend.h" +#include "replay/replay.h" #include @@ -448,7 +449,8 @@ BlockAIOCB *ide_issue_trim(BlockBackend *blk, iocb = blk_aio_get(&trim_aiocb_info, blk, cb, opaque); iocb->blk = blk; - iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb); + iocb->bh = qemu_bh_new_replay(ide_trim_bh_cb, iocb, + replay_get_current_step()); iocb->ret = 0; iocb->qiov = qiov; iocb->i = -1; diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c index 1452910..97784a0 100644 --- a/hw/timer/arm_timer.c +++ b/hw/timer/arm_timer.c @@ -168,7 +168,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq) s->freq = freq; s->control = TIMER_CTRL_IE; - bh = qemu_bh_new(arm_timer_tick, s); + bh = qemu_bh_new_replay(arm_timer_tick, s, 0); s->timer = ptimer_init(bh); vmstate_register(NULL, -1, &vmstate_arm_timer, s); return s; diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index f903de7..47ff9f4 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -1221,7 +1221,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev) USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); } } - s->bh = qemu_bh_new(uhci_bh, s); + s->bh = qemu_bh_new_replay(uhci_bh, s, 0); s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, uhci_frame_timer, s); s->num_ports_vmstate = NB_PORTS; QTAILQ_INIT(&s->queues); diff --git a/include/block/aio.h b/include/block/aio.h index 82cdf78..ed76b43 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -35,6 +35,8 @@ struct BlockAIOCB { const AIOCBInfo *aiocb_info; BlockDriverState *bs; BlockCompletionFunc *cb; + bool replay; + uint64_t replay_step; void *opaque; int refcnt; }; @@ -144,6 +146,17 @@ void aio_context_release(AioContext *ctx); QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque); /** + * aio_bh_new_replay: Allocate a new bottom half structure for replay. + * + * This function calls aio_bh_new function and also fills replay parameters + * of the BH structure. BH created with this function in record/replay mode + * are executed through the replay queue only at checkpoints and instructions + * executions. + */ +QEMUBH *aio_bh_new_replay(AioContext *ctx, QEMUBHFunc *cb, void *opaque, + uint64_t id); + +/** * aio_notify: Force processing of pending events. * * Similar to signaling a condition variable, aio_notify forces @@ -159,6 +172,11 @@ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque); void aio_notify(AioContext *ctx); /** + * aio_bh_call: Executes callback function of the specified BH. + */ +void aio_bh_call(void *opaque); + +/** * aio_bh_poll: Poll bottom halves for an AioContext. * * These are internal functions used by the QEMU main loop. diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index 62c68c0..f5a98fe 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -306,6 +306,7 @@ void qemu_iohandler_fill(GArray *pollfds); void qemu_iohandler_poll(GArray *pollfds, int rc); QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque); +QEMUBH *qemu_bh_new_replay(QEMUBHFunc *cb, void *opaque, uint64_t id); void qemu_bh_schedule_idle(QEMUBH *bh); #endif diff --git a/main-loop.c b/main-loop.c index 06aad06..87ebad4 100644 --- a/main-loop.c +++ b/main-loop.c @@ -514,3 +514,8 @@ QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque) { return aio_bh_new(qemu_aio_context, cb, opaque); } + +QEMUBH *qemu_bh_new_replay(QEMUBHFunc *cb, void *opaque, uint64_t id) +{ + return aio_bh_new_replay(qemu_aio_context, cb, opaque, id); +} diff --git a/replay/replay-events.c b/replay/replay-events.c index 409c9ad..ec15683 100755 --- a/replay/replay-events.c +++ b/replay/replay-events.c @@ -35,6 +35,9 @@ static bool events_enabled = false; static void replay_run_event(Event *event) { switch (event->event_kind) { + case REPLAY_ASYNC_EVENT_BH: + aio_bh_call(event->opaque); + break; default: error_report("Replay: invalid async event ID (%d) in the queue", event->event_kind); @@ -133,10 +136,18 @@ static void replay_save_event(Event *event, int checkpoint) /* save event-specific data */ switch (event->event_kind) { + case REPLAY_ASYNC_EVENT_BH: + replay_put_qword(event->id); + break; } } } +void replay_add_bh_event(void *bh, uint64_t id) +{ + replay_add_event_internal(REPLAY_ASYNC_EVENT_BH, bh, NULL, id); +} + /* Called with replay mutex locked */ void replay_save_events(int checkpoint) { @@ -168,6 +179,11 @@ static Event *replay_read_event(int checkpoint) /* Events that has not to be in the queue */ switch (read_event_kind) { + case REPLAY_ASYNC_EVENT_BH: + if (read_id == -1) { + read_id = replay_get_qword(); + } + break; default: error_report("Unknown ID %d of replay event", read_event_kind); exit(1); diff --git a/replay/replay-internal.h b/replay/replay-internal.h index f758371..29722cf 100755 --- a/replay/replay-internal.h +++ b/replay/replay-internal.h @@ -39,6 +39,7 @@ enum ReplayEvents { /* Asynchronous events IDs */ enum ReplayAsyncEventKind { + REPLAY_ASYNC_EVENT_BH, REPLAY_ASYNC_COUNT }; diff --git a/replay/replay.h b/replay/replay.h index 4c15efb..04fbce6 100755 --- a/replay/replay.h +++ b/replay/replay.h @@ -94,5 +94,7 @@ bool replay_checkpoint(ReplayCheckpoint checkpoint); void replay_disable_events(void); /*! Returns true when saving events is enabled */ bool replay_events_enabled(void); +/*! Adds BH event to the queue */ +void replay_add_bh_event(void *bh, uint64_t id); #endif diff --git a/stubs/replay.c b/stubs/replay.c index 1be3575..268f3e0 100755 --- a/stubs/replay.c +++ b/stubs/replay.c @@ -21,3 +21,7 @@ int runstate_is_running(void) { return 0; } + +void replay_add_bh_event(void *bh, uint64_t id) +{ +}