]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
replay: record and replay random number sources
authorPavel Dovgalyuk <pavel.dovgaluk@gmail.com>
Thu, 19 Dec 2019 12:50:48 +0000 (15:50 +0300)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 7 Jan 2020 11:08:39 +0000 (12:08 +0100)
Record/replay feature of icount allows deterministic running of execution
scenarios. Some CPUs and peripheral devices read random numbers from
external sources making deterministic execution impossible.
This patch adds recording and replaying of random read operations
into guest-random module, which is used by the virtual hardware.

Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
Message-Id: <157675984852.14505.15709141760677102489.stgit@pasha-Precision-3630-Tower>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
docs/replay.txt
include/sysemu/replay.h
replay/Makefile.objs
replay/replay-internal.h
replay/replay-random.c [new file with mode: 0644]
replay/replay.c
stubs/replay.c
util/guest-random.c

index ce97c3f72fc82db694741281818435f9a55ccad6..f4619a62a3d3ec31b3e5f1ddb5c565f5adbf8c6b 100644 (file)
@@ -67,6 +67,7 @@ Modifications of qemu include:
  * network filter for recording and replaying the packets
  * block driver for making block layer deterministic
  * serial port input record and replay
+ * recording of random numbers obtained from the external sources
 
 Locking and thread synchronisation
 ----------------------------------
index 8df517298c5e1af0331b84001707ca0b6dcdc527..5471bb514dfac7b288e28ed5ac0a0433c84ba2b6 100644 (file)
@@ -117,6 +117,13 @@ int64_t replay_read_clock(ReplayClockKind kind);
             ? replay_save_clock((clock), (value), cpu_get_icount_raw_locked()) \
         : (value))
 
+/* Processing data from random generators */
+
+/* Saves the values from the random number generator */
+void replay_save_random(int ret, void *buf, size_t len);
+/* Loads the saved values for the random number generator */
+int replay_read_random(void *buf, size_t len);
+
 /* Events */
 
 /*! Called when qemu shutdown is requested. */
index cee6539a235400f582c3c06a595b19121150d54a..939be964a91ee3b40073878bd2952ae2bece2667 100644 (file)
@@ -6,4 +6,5 @@ common-obj-y += replay-input.o
 common-obj-y += replay-char.o
 common-obj-y += replay-snapshot.o
 common-obj-y += replay-net.o
-common-obj-y += replay-audio.o
\ No newline at end of file
+common-obj-y += replay-audio.o
+common-obj-y += replay-random.o
index 55fca1ac6b4b487289e5aecd2e6c9cf5dc1721ec..33ac551e78ea92a6e3897531d26a01ae25140874 100644 (file)
@@ -34,6 +34,8 @@ enum ReplayEvents {
     EVENT_AUDIO_OUT,
     /* for audio in event */
     EVENT_AUDIO_IN,
+    /* for random number generator */
+    EVENT_RANDOM,
     /* for clock read/writes */
     /* some of greater codes are reserved for clocks */
     EVENT_CLOCK,
diff --git a/replay/replay-random.c b/replay/replay-random.c
new file mode 100644 (file)
index 0000000..afc7a0f
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * replay-random.c
+ *
+ * Copyright (c) 2010-2020 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/osdep.h"
+#include "qemu/error-report.h"
+#include "sysemu/replay.h"
+#include "replay-internal.h"
+
+void replay_save_random(int ret, void *buf, size_t len)
+{
+    g_assert(replay_mutex_locked());
+
+    replay_save_instructions();
+    replay_put_event(EVENT_RANDOM);
+    replay_put_dword(ret);
+    replay_put_array(buf, len);
+}
+
+int replay_read_random(void *buf, size_t len)
+{
+    int ret = 0;
+    g_assert(replay_mutex_locked());
+
+    replay_account_executed_instructions();
+    if (replay_next_event_is(EVENT_RANDOM)) {
+        size_t buf_size = 0;
+        ret = replay_get_dword();
+        replay_get_array(buf, &buf_size);
+        replay_finish_event();
+        g_assert(buf_size == len);
+    } else {
+        error_report("Missing random event in the replay log");
+        exit(1);
+    }
+    return ret;
+}
index 5cc25bd2f8c3adbfad347bdf380bfc55d6acfdf3..706c7b4f4b1f2c794bc1aa190d542b77d8d8d399 100644 (file)
@@ -22,7 +22,7 @@
 
 /* Current version of the replay mechanism.
    Increase it when file format changes. */
-#define REPLAY_VERSION              0xe02008
+#define REPLAY_VERSION              0xe02009
 /* Size of replay log header */
 #define HEADER_SIZE                 (sizeof(uint32_t) + sizeof(uint64_t))
 
index 10b3925e2ffb8ffa8c78a45089eb90d834c473b8..5974ec1f50e60f40fc90b12de6537460045b9cbd 100644 (file)
@@ -79,3 +79,12 @@ void replay_mutex_lock(void)
 void replay_mutex_unlock(void)
 {
 }
+
+void replay_save_random(int ret, void *buf, size_t len)
+{
+}
+
+int replay_read_random(void *buf, size_t len)
+{
+    return 0;
+}
index 9453968bd7243f4f18afd1dc6a2f01fb87097765..086115bd67026c4ef7b7004d1915ecb2d8cd7fcb 100644 (file)
@@ -14,6 +14,7 @@
 #include "qapi/error.h"
 #include "qemu/guest-random.h"
 #include "crypto/random.h"
+#include "sysemu/replay.h"
 
 
 static __thread GRand *thread_rand;
@@ -44,13 +45,21 @@ static int glib_random_bytes(void *buf, size_t len)
 
 int qemu_guest_getrandom(void *buf, size_t len, Error **errp)
 {
+    int ret;
+    if (replay_mode == REPLAY_MODE_PLAY) {
+        return replay_read_random(buf, len);
+    }
     if (unlikely(deterministic)) {
         /* Deterministic implementation using Glib's Mersenne Twister.  */
-        return glib_random_bytes(buf, len);
+        ret = glib_random_bytes(buf, len);
     } else {
         /* Non-deterministic implementation using crypto routines.  */
-        return qcrypto_random_bytes(buf, len, errp);
+        ret = qcrypto_random_bytes(buf, len, errp);
+    }
+    if (replay_mode == REPLAY_MODE_RECORD) {
+        replay_save_random(ret, buf, len);
     }
+    return ret;
 }
 
 void qemu_guest_getrandom_nofail(void *buf, size_t len)