]> git.proxmox.com Git - mirror_qemu.git/blame - replay/replay-internal.c
minikconf: do not include variables from MINIKCONF_ARGS in config-all-devices.mak
[mirror_qemu.git] / replay / replay-internal.c
CommitLineData
c92079f4
PD
1/*
2 * replay-internal.c
3 *
4 * Copyright (c) 2010-2015 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
d38ea87a 12#include "qemu/osdep.h"
26bc60ac 13#include "sysemu/replay.h"
c92079f4
PD
14#include "replay-internal.h"
15#include "qemu/error-report.h"
16#include "sysemu/sysemu.h"
17
c16861ef 18/* Mutex to protect reading and writing events to the log.
f186d64d 19 data_kind and has_unread_data are also protected
c16861ef
PD
20 by this mutex.
21 It also protects replay events queue which stores events to be
22 written or read to the log. */
23static QemuMutex lock;
24
c92079f4 25/* File for replay writing */
6dc0f529 26static bool write_error;
c92079f4
PD
27FILE *replay_file;
28
6dc0f529
PD
29static void replay_write_error(void)
30{
31 if (!write_error) {
32 error_report("replay write error");
33 write_error = true;
34 }
35}
36
0b570077
PM
37static void replay_read_error(void)
38{
39 error_report("error reading the replay data");
40 exit(1);
41}
42
c92079f4
PD
43void replay_put_byte(uint8_t byte)
44{
45 if (replay_file) {
6dc0f529
PD
46 if (putc(byte, replay_file) == EOF) {
47 replay_write_error();
48 }
c92079f4
PD
49 }
50}
51
52void replay_put_event(uint8_t event)
53{
26bc60ac 54 assert(event < EVENT_COUNT);
c92079f4
PD
55 replay_put_byte(event);
56}
57
58
59void replay_put_word(uint16_t word)
60{
61 replay_put_byte(word >> 8);
62 replay_put_byte(word);
63}
64
65void replay_put_dword(uint32_t dword)
66{
67 replay_put_word(dword >> 16);
68 replay_put_word(dword);
69}
70
71void replay_put_qword(int64_t qword)
72{
73 replay_put_dword(qword >> 32);
74 replay_put_dword(qword);
75}
76
77void replay_put_array(const uint8_t *buf, size_t size)
78{
79 if (replay_file) {
80 replay_put_dword(size);
6dc0f529
PD
81 if (fwrite(buf, 1, size, replay_file) != size) {
82 replay_write_error();
83 }
c92079f4
PD
84 }
85}
86
87uint8_t replay_get_byte(void)
88{
89 uint8_t byte = 0;
90 if (replay_file) {
0b570077
PM
91 int r = getc(replay_file);
92 if (r == EOF) {
93 replay_read_error();
94 }
95 byte = r;
c92079f4
PD
96 }
97 return byte;
98}
99
100uint16_t replay_get_word(void)
101{
102 uint16_t word = 0;
103 if (replay_file) {
104 word = replay_get_byte();
105 word = (word << 8) + replay_get_byte();
106 }
107
108 return word;
109}
110
111uint32_t replay_get_dword(void)
112{
113 uint32_t dword = 0;
114 if (replay_file) {
115 dword = replay_get_word();
116 dword = (dword << 16) + replay_get_word();
117 }
118
119 return dword;
120}
121
122int64_t replay_get_qword(void)
123{
124 int64_t qword = 0;
125 if (replay_file) {
126 qword = replay_get_dword();
127 qword = (qword << 32) + replay_get_dword();
128 }
129
130 return qword;
131}
132
133void replay_get_array(uint8_t *buf, size_t *size)
134{
135 if (replay_file) {
136 *size = replay_get_dword();
137 if (fread(buf, 1, *size, replay_file) != *size) {
0b570077 138 replay_read_error();
c92079f4
PD
139 }
140 }
141}
142
143void replay_get_array_alloc(uint8_t **buf, size_t *size)
144{
145 if (replay_file) {
146 *size = replay_get_dword();
147 *buf = g_malloc(*size);
148 if (fread(*buf, 1, *size, replay_file) != *size) {
0b570077 149 replay_read_error();
c92079f4
PD
150 }
151 }
152}
153
154void replay_check_error(void)
155{
156 if (replay_file) {
157 if (feof(replay_file)) {
158 error_report("replay file is over");
159 qemu_system_vmstop_request_prepare();
160 qemu_system_vmstop_request(RUN_STATE_PAUSED);
161 } else if (ferror(replay_file)) {
162 error_report("replay file is over or something goes wrong");
163 qemu_system_vmstop_request_prepare();
164 qemu_system_vmstop_request(RUN_STATE_INTERNAL_ERROR);
165 }
166 }
167}
168
169void replay_fetch_data_kind(void)
170{
171 if (replay_file) {
f186d64d
PD
172 if (!replay_state.has_unread_data) {
173 replay_state.data_kind = replay_get_byte();
174 if (replay_state.data_kind == EVENT_INSTRUCTION) {
26bc60ac
PD
175 replay_state.instructions_count = replay_get_dword();
176 }
c92079f4 177 replay_check_error();
f186d64d
PD
178 replay_state.has_unread_data = 1;
179 if (replay_state.data_kind >= EVENT_COUNT) {
180 error_report("Replay: unknown event kind %d",
181 replay_state.data_kind);
26bc60ac
PD
182 exit(1);
183 }
c92079f4
PD
184 }
185 }
186}
187
188void replay_finish_event(void)
189{
f186d64d 190 replay_state.has_unread_data = 0;
c92079f4
PD
191 replay_fetch_data_kind();
192}
c16861ef 193
180d30be
AB
194static __thread bool replay_locked;
195
c16861ef
PD
196void replay_mutex_init(void)
197{
198 qemu_mutex_init(&lock);
d759c951
AB
199 /* Hold the mutex while we start-up */
200 qemu_mutex_lock(&lock);
201 replay_locked = true;
c16861ef
PD
202}
203
a36544d3 204bool replay_mutex_locked(void)
180d30be
AB
205{
206 return replay_locked;
207}
208
d759c951 209/* Ordering constraints, replay_lock must be taken before BQL */
c16861ef
PD
210void replay_mutex_lock(void)
211{
d759c951
AB
212 if (replay_mode != REPLAY_MODE_NONE) {
213 g_assert(!qemu_mutex_iothread_locked());
214 g_assert(!replay_mutex_locked());
215 qemu_mutex_lock(&lock);
216 replay_locked = true;
217 }
c16861ef
PD
218}
219
220void replay_mutex_unlock(void)
221{
d759c951
AB
222 if (replay_mode != REPLAY_MODE_NONE) {
223 g_assert(replay_mutex_locked());
224 replay_locked = false;
225 qemu_mutex_unlock(&lock);
226 }
c16861ef 227}
26bc60ac 228
74c0b816
PB
229void replay_advance_current_step(uint64_t current_step)
230{
231 int diff = (int)(replay_get_current_step() - replay_state.current_step);
232
233 /* Time can only go forward */
234 assert(diff >= 0);
235
236 if (diff > 0) {
237 replay_put_event(EVENT_INSTRUCTION);
238 replay_put_dword(diff);
239 replay_state.current_step += diff;
240 }
241}
242
26bc60ac
PD
243/*! Saves cached instructions. */
244void replay_save_instructions(void)
245{
246 if (replay_file && replay_mode == REPLAY_MODE_RECORD) {
d759c951 247 g_assert(replay_mutex_locked());
74c0b816 248 replay_advance_current_step(replay_get_current_step());
26bc60ac
PD
249 }
250}