4 * Copyright (c) 2010-2015 Institute for System Programming
5 * of the Russian Academy of Sciences.
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.
12 #include "qemu-common.h"
13 #include "sysemu/replay.h"
14 #include "replay-internal.h"
15 #include "qemu/error-report.h"
16 #include "sysemu/sysemu.h"
18 unsigned int replay_data_kind
= -1;
19 static unsigned int replay_has_unread_data
;
21 /* Mutex to protect reading and writing events to the log.
22 replay_data_kind and replay_has_unread_data are also protected
24 It also protects replay events queue which stores events to be
25 written or read to the log. */
26 static QemuMutex lock
;
28 /* File for replay writing */
31 void replay_put_byte(uint8_t byte
)
34 putc(byte
, replay_file
);
38 void replay_put_event(uint8_t event
)
40 assert(event
< EVENT_COUNT
);
41 replay_put_byte(event
);
45 void replay_put_word(uint16_t word
)
47 replay_put_byte(word
>> 8);
48 replay_put_byte(word
);
51 void replay_put_dword(uint32_t dword
)
53 replay_put_word(dword
>> 16);
54 replay_put_word(dword
);
57 void replay_put_qword(int64_t qword
)
59 replay_put_dword(qword
>> 32);
60 replay_put_dword(qword
);
63 void replay_put_array(const uint8_t *buf
, size_t size
)
66 replay_put_dword(size
);
67 fwrite(buf
, 1, size
, replay_file
);
71 uint8_t replay_get_byte(void)
75 byte
= getc(replay_file
);
80 uint16_t replay_get_word(void)
84 word
= replay_get_byte();
85 word
= (word
<< 8) + replay_get_byte();
91 uint32_t replay_get_dword(void)
95 dword
= replay_get_word();
96 dword
= (dword
<< 16) + replay_get_word();
102 int64_t replay_get_qword(void)
106 qword
= replay_get_dword();
107 qword
= (qword
<< 32) + replay_get_dword();
113 void replay_get_array(uint8_t *buf
, size_t *size
)
116 *size
= replay_get_dword();
117 if (fread(buf
, 1, *size
, replay_file
) != *size
) {
118 error_report("replay read error");
123 void replay_get_array_alloc(uint8_t **buf
, size_t *size
)
126 *size
= replay_get_dword();
127 *buf
= g_malloc(*size
);
128 if (fread(*buf
, 1, *size
, replay_file
) != *size
) {
129 error_report("replay read error");
134 void replay_check_error(void)
137 if (feof(replay_file
)) {
138 error_report("replay file is over");
139 qemu_system_vmstop_request_prepare();
140 qemu_system_vmstop_request(RUN_STATE_PAUSED
);
141 } else if (ferror(replay_file
)) {
142 error_report("replay file is over or something goes wrong");
143 qemu_system_vmstop_request_prepare();
144 qemu_system_vmstop_request(RUN_STATE_INTERNAL_ERROR
);
149 void replay_fetch_data_kind(void)
152 if (!replay_has_unread_data
) {
153 replay_data_kind
= replay_get_byte();
154 if (replay_data_kind
== EVENT_INSTRUCTION
) {
155 replay_state
.instructions_count
= replay_get_dword();
157 replay_check_error();
158 replay_has_unread_data
= 1;
159 if (replay_data_kind
>= EVENT_COUNT
) {
160 error_report("Replay: unknown event kind %d", replay_data_kind
);
167 void replay_finish_event(void)
169 replay_has_unread_data
= 0;
170 replay_fetch_data_kind();
173 void replay_mutex_init(void)
175 qemu_mutex_init(&lock
);
178 void replay_mutex_destroy(void)
180 qemu_mutex_destroy(&lock
);
183 void replay_mutex_lock(void)
185 qemu_mutex_lock(&lock
);
188 void replay_mutex_unlock(void)
190 qemu_mutex_unlock(&lock
);
193 /*! Saves cached instructions. */
194 void replay_save_instructions(void)
196 if (replay_file
&& replay_mode
== REPLAY_MODE_RECORD
) {
198 int diff
= (int)(replay_get_current_step() - replay_state
.current_step
);
200 replay_put_event(EVENT_INSTRUCTION
);
201 replay_put_dword(diff
);
202 replay_state
.current_step
+= diff
;
204 replay_mutex_unlock();