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 <pavel.dovga...@ispras.ru> > --- > 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