All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
To: qemu-devel@nongnu.org
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, fred.konrad@greensocs.com
Subject: [Qemu-devel] [RFC PATCH v12 12/21] replay: recording and replaying clock ticks
Date: Tue, 05 May 2015 13:18:43 +0300	[thread overview]
Message-ID: <20150505101843.16764.5382.stgit@PASHA-ISP> (raw)
In-Reply-To: <20150505101732.16764.93601.stgit@PASHA-ISP>

Clock ticks are considered as the sources of non-deterministic data for
virtual machine. This patch implements saving the clock values when they
are acquired (virtual, host clock).
When replaying the execution corresponding values are read from log and
transfered to the module, which wants to read the values.
Such a design required the clock polling to be synchronized. Sometimes
it is not true - e.g. when timeouts for timer lists are checked. In this case
we use a cached value of the clock, passing it to the client code.

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
---
 cpus.c                   |    3 +-
 qemu-timer.c             |    7 +++--
 replay/Makefile.objs     |    1 +
 replay/replay-internal.h |   11 ++++++++
 replay/replay-time.c     |   64 ++++++++++++++++++++++++++++++++++++++++++++++
 replay/replay.h          |   23 +++++++++++++++++
 stubs/replay.c           |    9 ++++++
 7 files changed, 114 insertions(+), 4 deletions(-)
 create mode 100755 replay/replay-time.c

diff --git a/cpus.c b/cpus.c
index a7aff77..3f33e0c 100644
--- a/cpus.c
+++ b/cpus.c
@@ -336,7 +336,8 @@ static void icount_warp_rt(void *opaque)
 
     seqlock_write_lock(&timers_state.vm_clock_seqlock);
     if (runstate_is_running()) {
-        int64_t clock = cpu_get_clock_locked();
+        int64_t clock = REPLAY_CLOCK(REPLAY_CLOCK_VIRTUAL_RT,
+                                     cpu_get_clock_locked());
         int64_t warp_delta;
 
         warp_delta = clock - vm_clock_warp_start;
diff --git a/qemu-timer.c b/qemu-timer.c
index 5741f0d..d605afd 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -24,6 +24,7 @@
 
 #include "qemu/main-loop.h"
 #include "qemu/timer.h"
+#include "replay/replay.h"
 
 #ifdef CONFIG_POSIX
 #include <pthread.h>
@@ -570,15 +571,15 @@ int64_t qemu_clock_get_ns(QEMUClockType type)
             return cpu_get_clock();
         }
     case QEMU_CLOCK_HOST:
-        now = get_clock_realtime();
+        now = REPLAY_CLOCK(REPLAY_CLOCK_HOST, get_clock_realtime());
         last = clock->last;
         clock->last = now;
-        if (now < last) {
+        if (now < last && replay_mode == REPLAY_MODE_NONE) {
             notifier_list_notify(&clock->reset_notifiers, &now);
         }
         return now;
     case QEMU_CLOCK_VIRTUAL_RT:
-        return cpu_get_clock();
+        return REPLAY_CLOCK(REPLAY_CLOCK_VIRTUAL_RT, cpu_get_clock());
     }
 }
 
diff --git a/replay/Makefile.objs b/replay/Makefile.objs
index 56da09c..257c320 100755
--- a/replay/Makefile.objs
+++ b/replay/Makefile.objs
@@ -1,3 +1,4 @@
 obj-y += replay.o
 obj-y += replay-internal.o
 obj-y += replay-events.o
+obj-y += replay-time.o
diff --git a/replay/replay-internal.h b/replay/replay-internal.h
index 35c615a..a79f4af 100755
--- a/replay/replay-internal.h
+++ b/replay/replay-internal.h
@@ -23,6 +23,10 @@ enum ReplayEvents {
     EVENT_EXCEPTION,
     /* for async events */
     EVENT_ASYNC,
+    /* for clock read/writes */
+    /* some of grteater codes are reserved for clocks */
+    EVENT_CLOCK,
+    EVENT_CLOCK_LAST = EVENT_CLOCK + REPLAY_CLOCK_COUNT - 1,
     EVENT_COUNT
 };
 
@@ -35,6 +39,8 @@ enum ReplayAsyncEventKind {
 typedef enum ReplayAsyncEventKind ReplayAsyncEventKind;
 
 typedef struct ReplayState {
+    /*! Cached clock values. */
+    int64_t cached_clock[REPLAY_CLOCK_COUNT];
     /*! Current step - number of processed instructions and timer events. */
     uint64_t current_step;
     /*! Number of instructions to be executed before other events happen. */
@@ -85,6 +91,11 @@ void replay_save_instructions(void);
     \return true, if event was found */
 bool replay_next_event_is(int event);
 
+/*! Reads next clock value from the file.
+    If clock kind read from the file is different from the parameter,
+    the value is not used. */
+void replay_read_next_clock(unsigned int kind);
+
 /* Asynchronous events queue */
 
 /*! Initializes events' processing internals */
diff --git a/replay/replay-time.c b/replay/replay-time.c
new file mode 100755
index 0000000..2740901
--- /dev/null
+++ b/replay/replay-time.c
@@ -0,0 +1,64 @@
+/*
+ * replay-time.c
+ *
+ * Copyright (c) 2010-2015 Institute for System Programming
+ *                         of the Russian Academy of Sciences.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "replay.h"
+#include "replay-internal.h"
+
+
+int64_t replay_save_clock(ReplayClockKind kind, int64_t clock)
+{
+    replay_save_instructions();
+
+    if (replay_file) {
+        replay_mutex_lock();
+        replay_put_event(EVENT_CLOCK + kind);
+        replay_put_qword(clock);
+        replay_mutex_unlock();
+    }
+
+    return clock;
+}
+
+void replay_read_next_clock(ReplayClockKind kind)
+{
+    unsigned int read_kind = replay_data_kind - EVENT_CLOCK;
+
+    assert(read_kind == kind);
+
+    int64_t clock = replay_get_qword();
+
+    replay_check_error();
+    replay_finish_event();
+
+    replay_state.cached_clock[read_kind] = clock;
+}
+
+/*! Reads next clock event from the input. */
+int64_t replay_read_clock(ReplayClockKind kind)
+{
+    replay_account_executed_instructions();
+
+    if (replay_file) {
+        int64_t ret;
+        replay_mutex_lock();
+        if (replay_next_event_is(EVENT_CLOCK + kind)) {
+            replay_read_next_clock(kind);
+        }
+        ret = replay_state.cached_clock[kind];
+        replay_mutex_unlock();
+
+        return ret;
+    }
+
+    error_report("REPLAY INTERNAL ERROR %d", __LINE__);
+    exit(1);
+}
diff --git a/replay/replay.h b/replay/replay.h
index c2a7651..2398509 100755
--- a/replay/replay.h
+++ b/replay/replay.h
@@ -16,6 +16,16 @@
 #include <stdint.h>
 #include "qapi-types.h"
 
+/* replay clock kinds */
+enum ReplayClockKind {
+    /* host_clock */
+    REPLAY_CLOCK_HOST,
+    /* virtual_rt_clock */
+    REPLAY_CLOCK_VIRTUAL_RT,
+    REPLAY_CLOCK_COUNT
+};
+typedef enum ReplayClockKind ReplayClockKind;
+
 extern ReplayMode replay_mode;
 
 /* Processing the instructions */
@@ -43,6 +53,19 @@ bool replay_interrupt(void);
     Returns true, when interrupt request is pending */
 bool replay_has_interrupt(void);
 
+/* Processing clocks and other time sources */
+
+/*! Save the specified clock */
+int64_t replay_save_clock(ReplayClockKind kind, int64_t clock);
+/*! Read the specified clock from the log or return cached data */
+int64_t replay_read_clock(ReplayClockKind kind);
+/*! Saves or reads the clock depending on the current replay mode. */
+#define REPLAY_CLOCK(clock, value)                                      \
+    (replay_mode == REPLAY_MODE_PLAY ? replay_read_clock((clock))       \
+        : replay_mode == REPLAY_MODE_RECORD                             \
+            ? replay_save_clock((clock), (value))                       \
+        : (value))
+
 /* Asynchronous events queue */
 
 /*! Disables storing events in the queue */
diff --git a/stubs/replay.c b/stubs/replay.c
index 563c777..121bca6 100755
--- a/stubs/replay.c
+++ b/stubs/replay.c
@@ -1,3 +1,12 @@
 #include "replay/replay.h"
 
 ReplayMode replay_mode;
+
+int64_t replay_save_clock(unsigned int kind, int64_t clock)
+{
+}
+
+int64_t replay_read_clock(unsigned int kind)
+{
+    return 0;
+}

  parent reply	other threads:[~2015-05-05 10:18 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-05 10:17 [Qemu-devel] [RFC PATCH v12 00/21] Deterministic replay core Pavel Dovgalyuk
2015-05-05 10:17 ` [Qemu-devel] [RFC PATCH v12 01/21] i386: partial revert of interrupt poll fix Pavel Dovgalyuk
2015-05-05 10:17 ` [Qemu-devel] [RFC PATCH v12 02/21] replay: global variables and function stubs Pavel Dovgalyuk
2015-05-05 10:17 ` [Qemu-devel] [RFC PATCH v12 03/21] sysemu: system functions for replay Pavel Dovgalyuk
2015-05-05 10:17 ` [Qemu-devel] [RFC PATCH v12 04/21] replay: internal functions for replay log Pavel Dovgalyuk
2015-05-05 10:18 ` [Qemu-devel] [RFC PATCH v12 05/21] replay: introduce mutex to protect the " Pavel Dovgalyuk
2015-05-05 10:18 ` [Qemu-devel] [RFC PATCH v12 06/21] replay: introduce icount event Pavel Dovgalyuk
2015-05-05 10:18 ` [Qemu-devel] [RFC PATCH v12 07/21] cpu-exec: allow temporary disabling icount Pavel Dovgalyuk
2015-05-05 10:18 ` [Qemu-devel] [RFC PATCH v12 08/21] cpu: replay instructions sequence Pavel Dovgalyuk
2015-05-05 10:18 ` [Qemu-devel] [RFC PATCH v12 09/21] i386: interrupt poll processing Pavel Dovgalyuk
2015-05-05 10:18 ` [Qemu-devel] [RFC PATCH v12 10/21] replay: interrupts and exceptions Pavel Dovgalyuk
2015-05-05 10:18 ` [Qemu-devel] [RFC PATCH v12 11/21] replay: asynchronous events infrastructure Pavel Dovgalyuk
2015-05-05 10:18 ` Pavel Dovgalyuk [this message]
2015-05-05 10:18 ` [Qemu-devel] [RFC PATCH v12 13/21] replay: shutdown event Pavel Dovgalyuk
2015-05-05 10:18 ` [Qemu-devel] [RFC PATCH v12 14/21] replay: checkpoints Pavel Dovgalyuk
2015-05-05 10:19 ` [Qemu-devel] [RFC PATCH v12 15/21] aio: replace stack of bottom halves with queue Pavel Dovgalyuk
2015-05-05 10:19 ` [Qemu-devel] [RFC PATCH v12 16/21] Pavel Dovgalyuk
2015-05-05 10:22   ` Pavel Dovgaluk
2015-05-05 10:47     ` Paolo Bonzini
2015-05-06  7:25       ` Pavel Dovgaluk
2015-05-05 11:09   ` Peter Maydell
2015-05-05 10:19 ` [Qemu-devel] [RFC PATCH v12 17/21] typedef: add typedef for QemuOpts Pavel Dovgalyuk
2015-05-05 10:19 ` [Qemu-devel] [RFC PATCH v12 18/21] replay: initialization and deinitialization Pavel Dovgalyuk
2015-05-05 10:19 ` [Qemu-devel] [RFC PATCH v12 19/21] replay: replay blockers for devices Pavel Dovgalyuk
2015-05-05 10:19 ` [Qemu-devel] [RFC PATCH v12 20/21] replay: command line options Pavel Dovgalyuk
2015-05-05 10:19 ` [Qemu-devel] [RFC PATCH v12 21/21] replay: recording of the user input Pavel Dovgalyuk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150505101843.16764.5382.stgit@PASHA-ISP \
    --to=pavel.dovgaluk@ispras.ru \
    --cc=alex.bennee@linaro.org \
    --cc=batuzovk@ispras.ru \
    --cc=fred.konrad@greensocs.com \
    --cc=maria.klimushenkova@ispras.ru \
    --cc=mark.burton@greensocs.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.crosthwaite@xilinx.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=real@ispras.ru \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.