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, afaerber@suse.de, fred.konrad@greensocs.com
Subject: [Qemu-devel] [RFC PATCH v6 24/32] replay: recording and replaying different timers
Date: Mon, 08 Dec 2014 10:55:15 +0300 [thread overview]
Message-ID: <20141208075514.7108.19302.stgit@PASHA-ISP> (raw)
In-Reply-To: <20141208075255.7108.19079.stgit@PASHA-ISP>
This patch introduces functions for recording and replaying realtime sources,
that do not use qemu-clock interface. These include return value of time()
function in time_t and struct tm forms. Patch also adds warning to
get_timedate function to prevent its usage in recording mode, because it may
lead to non-determinism.
Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
---
hw/timer/mc146818rtc.c | 10 ++++
hw/timer/pl031.c | 10 ++++
include/qemu-common.h | 1
replay/replay-internal.h | 4 ++
replay/replay-time.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++
replay/replay.h | 8 +++
vl.c | 17 ++++++-
7 files changed, 157 insertions(+), 5 deletions(-)
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index f18d128..7e27931 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -28,6 +28,7 @@
#include "qapi/visitor.h"
#include "qapi-event.h"
#include "qmp-commands.h"
+#include "replay/replay.h"
#ifdef TARGET_I386
#include "hw/i386/apic.h"
@@ -703,7 +704,14 @@ static void rtc_set_date_from_host(ISADevice *dev)
RTCState *s = MC146818_RTC(dev);
struct tm tm;
- qemu_get_timedate(&tm, 0);
+ if (replay_mode == REPLAY_MODE_RECORD) {
+ qemu_get_timedate_no_warning(&tm, 0);
+ replay_save_tm(&tm);
+ } else if (replay_mode == REPLAY_MODE_PLAY) {
+ replay_read_tm(&tm);
+ } else {
+ qemu_get_timedate_no_warning(&tm, 0);
+ }
s->base_rtc = mktimegm(&tm);
s->last_update = qemu_clock_get_ns(rtc_clock);
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
index 34d9b44..19264f2 100644
--- a/hw/timer/pl031.c
+++ b/hw/timer/pl031.c
@@ -14,6 +14,7 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
+#include "replay/replay.h"
//#define DEBUG_PL031
@@ -200,7 +201,14 @@ static int pl031_init(SysBusDevice *dev)
sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq);
- qemu_get_timedate(&tm, 0);
+ if (replay_mode == REPLAY_MODE_RECORD) {
+ qemu_get_timedate_no_warning(&tm, 0);
+ replay_save_tm(&tm);
+ } else if (replay_mode == REPLAY_MODE_PLAY) {
+ replay_read_tm(&tm);
+ } else {
+ qemu_get_timedate_no_warning(&tm, 0);
+ }
s->tick_offset = mktimegm(&tm) -
qemu_clock_get_ns(rtc_clock) / get_ticks_per_sec();
diff --git a/include/qemu-common.h b/include/qemu-common.h
index f862214..e30adc5 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -129,6 +129,7 @@ void dump_drift_info(FILE *f, fprintf_function cpu_fprintf);
int qemu_main(int argc, char **argv, char **envp);
#endif
+void qemu_get_timedate_no_warning(struct tm *tm, int offset);
void qemu_get_timedate(struct tm *tm, int offset);
int qemu_timedate_diff(struct tm *tm);
diff --git a/replay/replay-internal.h b/replay/replay-internal.h
index c36d7de..009029d 100755
--- a/replay/replay-internal.h
+++ b/replay/replay-internal.h
@@ -14,6 +14,10 @@
#include <stdio.h>
+/* for time_t event */
+#define EVENT_TIME_T 1
+/* for tm event */
+#define EVENT_TM 2
/* for software interrupt */
#define EVENT_INTERRUPT 15
/* for emulated exceptions */
diff --git a/replay/replay-time.c b/replay/replay-time.c
index 3f94f4e..5d944d3 100755
--- a/replay/replay-time.c
+++ b/replay/replay-time.c
@@ -77,3 +77,115 @@ int64_t replay_read_clock(unsigned int kind)
fprintf(stderr, "REPLAY INTERNAL ERROR %d\n", __LINE__);
exit(1);
}
+
+/*! Saves time_t value to the log */
+static void replay_save_time_t(time_t tm)
+{
+ replay_save_instructions();
+
+ if (replay_file) {
+ replay_put_event(EVENT_TIME_T);
+ if (sizeof(tm) == 4) {
+ replay_put_dword(tm);
+ } else if (sizeof(tm) == 8) {
+ replay_put_qword(tm);
+ } else {
+ fprintf(stderr, "invalid time_t sizeof: %u\n",
+ (unsigned)sizeof(tm));
+ exit(1);
+ }
+ }
+}
+
+/*! Reads time_t value from the log. Stops execution in case of error */
+static time_t replay_read_time_t(void)
+{
+ replay_exec_instructions();
+
+ if (replay_file) {
+ time_t tm;
+
+ skip_async_events_until(EVENT_TIME_T);
+
+ if (sizeof(tm) == 4) {
+ tm = replay_get_dword();
+ } else if (sizeof(tm) == 8) {
+ tm = replay_get_qword();
+ } else {
+ fprintf(stderr, "invalid time_t sizeof: %u\n",
+ (unsigned)sizeof(tm));
+ exit(1);
+ }
+
+ replay_check_error();
+
+ replay_has_unread_data = 0;
+
+ return tm;
+ }
+
+ fprintf(stderr, "REPLAY INTERNAL ERROR %d\n", __LINE__);
+ exit(1);
+}
+
+void replay_save_tm(struct tm *tm)
+{
+ replay_save_instructions();
+
+ if (replay_file) {
+ replay_put_event(EVENT_TM);
+
+ replay_put_dword(tm->tm_sec);
+ replay_put_dword(tm->tm_min);
+ replay_put_dword(tm->tm_hour);
+ replay_put_dword(tm->tm_mday);
+ replay_put_dword(tm->tm_mon);
+ replay_put_dword(tm->tm_year);
+ replay_put_dword(tm->tm_wday);
+ replay_put_dword(tm->tm_yday);
+ replay_put_dword(tm->tm_isdst);
+ }
+}
+
+void replay_read_tm(struct tm *tm)
+{
+ replay_exec_instructions();
+
+ if (replay_file) {
+ skip_async_events_until(EVENT_TM);
+
+ tm->tm_sec = replay_get_dword();
+ tm->tm_min = replay_get_dword();
+ tm->tm_hour = replay_get_dword();
+ tm->tm_mday = replay_get_dword();
+ tm->tm_mon = replay_get_dword();
+ tm->tm_year = replay_get_dword();
+ tm->tm_wday = replay_get_dword();
+ tm->tm_yday = replay_get_dword();
+ tm->tm_isdst = replay_get_dword();
+
+ replay_check_error();
+ replay_has_unread_data = 0;
+
+ return;
+ }
+
+ fprintf(stderr, "REPLAY INTERNAL ERROR %d\n", __LINE__);
+ exit(1);
+}
+
+time_t replay_time(void)
+{
+ time_t systime;
+
+ if (replay_mode == REPLAY_MODE_RECORD) {
+ systime = time(NULL);
+ replay_save_time_t(systime);
+ } else if (replay_mode == REPLAY_MODE_PLAY) {
+ systime = replay_read_time_t();
+ } else {
+ systime = time(NULL);
+ }
+
+ return systime;
+}
diff --git a/replay/replay.h b/replay/replay.h
index 1c18c0e..0c02e03 100755
--- a/replay/replay.h
+++ b/replay/replay.h
@@ -14,6 +14,7 @@
#include <stdbool.h>
#include <stdint.h>
+#include <time.h>
#include "qapi-types.h"
/* replay clock kinds */
@@ -69,6 +70,13 @@ int64_t replay_read_clock(unsigned int kind);
: replay_mode == REPLAY_MODE_RECORD \
? replay_save_clock((clock), (value)) \
: (value))
+/*! Returns result of time() function execution in normal and record modes.
+ In play mode returns value read from the log. */
+time_t replay_time(void);
+/*! Saves struct tm value to the log */
+void replay_save_tm(struct tm *tm);
+/*! Reads struct tm value from the log. Stops execution in case of error */
+void replay_read_tm(struct tm *tm);
/* Asynchronous events queue */
diff --git a/vl.c b/vl.c
index eb89d62..c62507d 100644
--- a/vl.c
+++ b/vl.c
@@ -118,6 +118,7 @@ int main(int argc, char **argv)
#include "qapi/opts-visitor.h"
#include "qom/object_interfaces.h"
#include "qapi-event.h"
+#include "replay/replay.h"
#define DEFAULT_RAM_SIZE 128
@@ -774,7 +775,7 @@ void vm_start(void)
/***********************************************************/
/* host time/date access */
-void qemu_get_timedate(struct tm *tm, int offset)
+void qemu_get_timedate_no_warning(struct tm *tm, int offset)
{
time_t ti;
@@ -791,6 +792,16 @@ void qemu_get_timedate(struct tm *tm, int offset)
}
}
+/* host time/date access with replay warning */
+void qemu_get_timedate(struct tm *tm, int offset)
+{
+ if (replay_mode == REPLAY_MODE_RECORD) {
+ fprintf(stderr, "REPLAY WARNING! qemu_get_timedate "
+ "function may lead to non-determinism\n");
+ }
+ qemu_get_timedate_no_warning(tm, offset);
+}
+
int qemu_timedate_diff(struct tm *tm)
{
time_t seconds;
@@ -806,7 +817,7 @@ int qemu_timedate_diff(struct tm *tm)
else
seconds = mktimegm(tm) + rtc_date_offset;
- return seconds - time(NULL);
+ return seconds - replay_time();
}
static void configure_rtc_date_offset(const char *startdate, int legacy)
@@ -844,7 +855,7 @@ static void configure_rtc_date_offset(const char *startdate, int legacy)
"'2006-06-17T16:01:21' or '2006-06-17'\n");
exit(1);
}
- rtc_date_offset = time(NULL) - rtc_start_date;
+ rtc_date_offset = replay_time() - rtc_start_date;
}
}
next prev parent reply other threads:[~2014-12-08 7:55 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-12-08 7:53 [Qemu-devel] [RFC PATCH v6 00/32] Deterministic replay core Pavel Dovgalyuk
2014-12-08 7:53 ` [Qemu-devel] [RFC PATCH v6 01/32] i386: partial revert of interrupt poll fix Pavel Dovgalyuk
2014-12-08 7:53 ` [Qemu-devel] [RFC PATCH v6 02/32] cpu-exec: fix cpu_exec_nocache Pavel Dovgalyuk
2014-12-08 7:53 ` [Qemu-devel] [RFC PATCH v6 03/32] icount: set can_do_io outside TB execution Pavel Dovgalyuk
2014-12-08 7:53 ` [Qemu-devel] [RFC PATCH v6 04/32] replay: global variables and function stubs Pavel Dovgalyuk
2014-12-08 7:53 ` [Qemu-devel] [RFC PATCH v6 05/32] sysemu: system functions for replay Pavel Dovgalyuk
2014-12-08 7:53 ` [Qemu-devel] [RFC PATCH v6 06/32] replay: internal functions for replay log Pavel Dovgalyuk
2014-12-08 7:53 ` [Qemu-devel] [RFC PATCH v6 07/32] cpu-exec: reset exception_index correctly Pavel Dovgalyuk
2014-12-08 7:53 ` [Qemu-devel] [RFC PATCH v6 08/32] icount: implement icount requesting Pavel Dovgalyuk
2014-12-09 17:39 ` Paolo Bonzini
2014-12-10 6:35 ` Pavel Dovgalyuk
2014-12-10 7:41 ` Paolo Bonzini
2014-12-11 8:16 ` Pavel Dovgaluk
[not found] ` <5947.68890082396$1418285825@news.gmane.org>
2014-12-11 11:06 ` Paolo Bonzini
2014-12-08 7:53 ` [Qemu-devel] [RFC PATCH v6 09/32] replay: introduce icount event Pavel Dovgalyuk
2014-12-08 12:47 ` Gonglei
2014-12-08 7:53 ` [Qemu-devel] [RFC PATCH v6 10/32] i386: do not cross the pages boundaries in replay mode Pavel Dovgalyuk
2014-12-08 7:54 ` [Qemu-devel] [RFC PATCH v6 11/32] From 7abf2f72777958d395cfd01d97fe707cc06152b5 Mon Sep 17 00:00:00 2001 Pavel Dovgalyuk
2014-12-17 13:02 ` Alexander Graf
2014-12-08 7:54 ` [Qemu-devel] [RFC PATCH v6 12/32] From 185a3a47d08857a66332ae862b372a153ce92bb9 " Pavel Dovgalyuk
2014-12-08 7:54 ` [Qemu-devel] [RFC PATCH v6 13/32] From a0cb9e80ba0de409b5ad556109a1c71ce4d8ce19 " Pavel Dovgalyuk
2014-12-08 7:54 ` [Qemu-devel] [RFC PATCH v6 14/32] From 04bbd21134dd2c6b7309a7f5f2b780aae2757003 " Pavel Dovgalyuk
2014-12-08 7:54 ` [Qemu-devel] [RFC PATCH v6 15/32] cpu-exec: allow temporary disabling icount Pavel Dovgalyuk
2014-12-08 7:54 ` [Qemu-devel] [RFC PATCH v6 16/32] cpu-exec: invalidate nocache translation if they are interrupted Pavel Dovgalyuk
2014-12-08 7:54 ` [Qemu-devel] [RFC PATCH v6 17/32] cpu: replay instructions sequence Pavel Dovgalyuk
2014-12-08 7:54 ` [Qemu-devel] [RFC PATCH v6 18/32] replay: interrupts and exceptions Pavel Dovgalyuk
2014-12-08 7:54 ` [Qemu-devel] [RFC PATCH v6 19/32] replay: asynchronous events infrastructure Pavel Dovgalyuk
2014-12-08 7:54 ` [Qemu-devel] [RFC PATCH v6 20/32] timer: introduce new QEMU_CLOCK_VIRTUAL_RT clock Pavel Dovgalyuk
2014-12-08 7:54 ` [Qemu-devel] [RFC PATCH v6 21/32] cpus: make icount warp deterministic in replay mode Pavel Dovgalyuk
2014-12-08 7:55 ` [Qemu-devel] [RFC PATCH v6 22/32] timer: fix usage of clock functions Pavel Dovgalyuk
2014-12-08 7:55 ` [Qemu-devel] [RFC PATCH v6 23/32] replay: recording and replaying clock ticks Pavel Dovgalyuk
2014-12-08 7:55 ` Pavel Dovgalyuk [this message]
2014-12-08 7:55 ` [Qemu-devel] [RFC PATCH v6 25/32] replay: shutdown event Pavel Dovgalyuk
2014-12-08 7:55 ` [Qemu-devel] [RFC PATCH v6 26/32] replay: checkpoints Pavel Dovgalyuk
2014-12-08 7:55 ` [Qemu-devel] [RFC PATCH v6 27/32] replay: bottom halves Pavel Dovgalyuk
2014-12-08 7:55 ` [Qemu-devel] [RFC PATCH v6 28/32] replay: replay aio requests Pavel Dovgalyuk
2014-12-08 7:55 ` [Qemu-devel] [RFC PATCH v6 29/32] replay: thread pool Pavel Dovgalyuk
2014-12-08 7:55 ` [Qemu-devel] [RFC PATCH v6 30/32] replay: initialization and deinitialization Pavel Dovgalyuk
2014-12-08 7:55 ` [Qemu-devel] [RFC PATCH v6 31/32] replay: command line options Pavel Dovgalyuk
2014-12-08 7:56 ` [Qemu-devel] [RFC PATCH v6 32/32] 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=20141208075514.7108.19302.stgit@PASHA-ISP \
--to=pavel.dovgaluk@ispras.ru \
--cc=afaerber@suse.de \
--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.