[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] replay: record and replay random number sources
From: |
Paolo Bonzini |
Subject: |
Re: [PATCH] replay: record and replay random number sources |
Date: |
Fri, 20 Dec 2019 14:14:10 +0100 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.1.1 |
On 19/12/19 13:50, Pavel Dovgalyuk wrote:
> 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 <address@hidden>
> ---
> docs/replay.txt | 1 +
> include/sysemu/replay.h | 7 +++++++
> replay/Makefile.objs | 3 ++-
> replay/replay-internal.h | 2 ++
> replay/replay-random.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
> replay/replay.c | 2 +-
> stubs/replay.c | 9 +++++++++
> util/guest-random.c | 13 +++++++++++--
> 8 files changed, 77 insertions(+), 4 deletions(-)
> create mode 100644 replay/replay-random.c
>
> diff --git a/docs/replay.txt b/docs/replay.txt
> index ce97c3f72f..f4619a62a3 100644
> --- a/docs/replay.txt
> +++ b/docs/replay.txt
> @@ -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
> ----------------------------------
> diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
> index 8df517298c..5471bb514d 100644
> --- a/include/sysemu/replay.h
> +++ b/include/sysemu/replay.h
> @@ -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. */
> diff --git a/replay/Makefile.objs b/replay/Makefile.objs
> index cee6539a23..939be964a9 100644
> --- a/replay/Makefile.objs
> +++ b/replay/Makefile.objs
> @@ -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
> diff --git a/replay/replay-internal.h b/replay/replay-internal.h
> index 55fca1ac6b..33ac551e78 100644
> --- a/replay/replay-internal.h
> +++ b/replay/replay-internal.h
> @@ -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
> index 0000000000..afc7a0fccc
> --- /dev/null
> +++ b/replay/replay-random.c
> @@ -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;
> +}
> diff --git a/replay/replay.c b/replay/replay.c
> index 5cc25bd2f8..706c7b4f4b 100644
> --- a/replay/replay.c
> +++ b/replay/replay.c
> @@ -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))
>
> diff --git a/stubs/replay.c b/stubs/replay.c
> index 10b3925e2f..5974ec1f50 100644
> --- a/stubs/replay.c
> +++ b/stubs/replay.c
> @@ -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;
> +}
> diff --git a/util/guest-random.c b/util/guest-random.c
> index 9453968bd7..086115bd67 100644
> --- a/util/guest-random.c
> +++ b/util/guest-random.c
> @@ -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)
>
Queued, thanks.
Paolo