qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

replay: record and replay random number sources

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>

authored by

Pavel Dovgalyuk and committed by
Paolo Bonzini
878ec29b fc6b2dba

+77 -4
+1
docs/replay.txt
··· 67 67 * network filter for recording and replaying the packets 68 68 * block driver for making block layer deterministic 69 69 * serial port input record and replay 70 + * recording of random numbers obtained from the external sources 70 71 71 72 Locking and thread synchronisation 72 73 ----------------------------------
+7
include/sysemu/replay.h
··· 117 117 ? replay_save_clock((clock), (value), cpu_get_icount_raw_locked()) \ 118 118 : (value)) 119 119 120 + /* Processing data from random generators */ 121 + 122 + /* Saves the values from the random number generator */ 123 + void replay_save_random(int ret, void *buf, size_t len); 124 + /* Loads the saved values for the random number generator */ 125 + int replay_read_random(void *buf, size_t len); 126 + 120 127 /* Events */ 121 128 122 129 /*! Called when qemu shutdown is requested. */
+2 -1
replay/Makefile.objs
··· 6 6 common-obj-y += replay-char.o 7 7 common-obj-y += replay-snapshot.o 8 8 common-obj-y += replay-net.o 9 - common-obj-y += replay-audio.o 9 + common-obj-y += replay-audio.o 10 + common-obj-y += replay-random.o
+2
replay/replay-internal.h
··· 34 34 EVENT_AUDIO_OUT, 35 35 /* for audio in event */ 36 36 EVENT_AUDIO_IN, 37 + /* for random number generator */ 38 + EVENT_RANDOM, 37 39 /* for clock read/writes */ 38 40 /* some of greater codes are reserved for clocks */ 39 41 EVENT_CLOCK,
+44
replay/replay-random.c
··· 1 + /* 2 + * replay-random.c 3 + * 4 + * Copyright (c) 2010-2020 Institute for System Programming 5 + * of the Russian Academy of Sciences. 6 + * 7 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 8 + * See the COPYING file in the top-level directory. 9 + * 10 + */ 11 + 12 + #include "qemu/osdep.h" 13 + #include "qemu/error-report.h" 14 + #include "sysemu/replay.h" 15 + #include "replay-internal.h" 16 + 17 + void replay_save_random(int ret, void *buf, size_t len) 18 + { 19 + g_assert(replay_mutex_locked()); 20 + 21 + replay_save_instructions(); 22 + replay_put_event(EVENT_RANDOM); 23 + replay_put_dword(ret); 24 + replay_put_array(buf, len); 25 + } 26 + 27 + int replay_read_random(void *buf, size_t len) 28 + { 29 + int ret = 0; 30 + g_assert(replay_mutex_locked()); 31 + 32 + replay_account_executed_instructions(); 33 + if (replay_next_event_is(EVENT_RANDOM)) { 34 + size_t buf_size = 0; 35 + ret = replay_get_dword(); 36 + replay_get_array(buf, &buf_size); 37 + replay_finish_event(); 38 + g_assert(buf_size == len); 39 + } else { 40 + error_report("Missing random event in the replay log"); 41 + exit(1); 42 + } 43 + return ret; 44 + }
+1 -1
replay/replay.c
··· 22 22 23 23 /* Current version of the replay mechanism. 24 24 Increase it when file format changes. */ 25 - #define REPLAY_VERSION 0xe02008 25 + #define REPLAY_VERSION 0xe02009 26 26 /* Size of replay log header */ 27 27 #define HEADER_SIZE (sizeof(uint32_t) + sizeof(uint64_t)) 28 28
+9
stubs/replay.c
··· 79 79 void replay_mutex_unlock(void) 80 80 { 81 81 } 82 + 83 + void replay_save_random(int ret, void *buf, size_t len) 84 + { 85 + } 86 + 87 + int replay_read_random(void *buf, size_t len) 88 + { 89 + return 0; 90 + }
+11 -2
util/guest-random.c
··· 14 14 #include "qapi/error.h" 15 15 #include "qemu/guest-random.h" 16 16 #include "crypto/random.h" 17 + #include "sysemu/replay.h" 17 18 18 19 19 20 static __thread GRand *thread_rand; ··· 44 45 45 46 int qemu_guest_getrandom(void *buf, size_t len, Error **errp) 46 47 { 48 + int ret; 49 + if (replay_mode == REPLAY_MODE_PLAY) { 50 + return replay_read_random(buf, len); 51 + } 47 52 if (unlikely(deterministic)) { 48 53 /* Deterministic implementation using Glib's Mersenne Twister. */ 49 - return glib_random_bytes(buf, len); 54 + ret = glib_random_bytes(buf, len); 50 55 } else { 51 56 /* Non-deterministic implementation using crypto routines. */ 52 - return qcrypto_random_bytes(buf, len, errp); 57 + ret = qcrypto_random_bytes(buf, len, errp); 53 58 } 59 + if (replay_mode == REPLAY_MODE_RECORD) { 60 + replay_save_random(ret, buf, len); 61 + } 62 + return ret; 54 63 } 55 64 56 65 void qemu_guest_getrandom_nofail(void *buf, size_t len)