]> git.proxmox.com Git - mirror_qemu.git/blame - replay/replay-internal.c
replay: Set error location properly when parsing options
[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"
c92079f4 13#include "qemu-common.h"
26bc60ac 14#include "sysemu/replay.h"
c92079f4
PD
15#include "replay-internal.h"
16#include "qemu/error-report.h"
17#include "sysemu/sysemu.h"
18
19unsigned int replay_data_kind = -1;
20static unsigned int replay_has_unread_data;
21
c16861ef
PD
22/* Mutex to protect reading and writing events to the log.
23 replay_data_kind and replay_has_unread_data are also protected
24 by this mutex.
25 It also protects replay events queue which stores events to be
26 written or read to the log. */
27static QemuMutex lock;
28
c92079f4
PD
29/* File for replay writing */
30FILE *replay_file;
31
32void replay_put_byte(uint8_t byte)
33{
34 if (replay_file) {
35 putc(byte, replay_file);
36 }
37}
38
39void replay_put_event(uint8_t event)
40{
26bc60ac 41 assert(event < EVENT_COUNT);
c92079f4
PD
42 replay_put_byte(event);
43}
44
45
46void replay_put_word(uint16_t word)
47{
48 replay_put_byte(word >> 8);
49 replay_put_byte(word);
50}
51
52void replay_put_dword(uint32_t dword)
53{
54 replay_put_word(dword >> 16);
55 replay_put_word(dword);
56}
57
58void replay_put_qword(int64_t qword)
59{
60 replay_put_dword(qword >> 32);
61 replay_put_dword(qword);
62}
63
64void replay_put_array(const uint8_t *buf, size_t size)
65{
66 if (replay_file) {
67 replay_put_dword(size);
68 fwrite(buf, 1, size, replay_file);
69 }
70}
71
72uint8_t replay_get_byte(void)
73{
74 uint8_t byte = 0;
75 if (replay_file) {
76 byte = getc(replay_file);
77 }
78 return byte;
79}
80
81uint16_t replay_get_word(void)
82{
83 uint16_t word = 0;
84 if (replay_file) {
85 word = replay_get_byte();
86 word = (word << 8) + replay_get_byte();
87 }
88
89 return word;
90}
91
92uint32_t replay_get_dword(void)
93{
94 uint32_t dword = 0;
95 if (replay_file) {
96 dword = replay_get_word();
97 dword = (dword << 16) + replay_get_word();
98 }
99
100 return dword;
101}
102
103int64_t replay_get_qword(void)
104{
105 int64_t qword = 0;
106 if (replay_file) {
107 qword = replay_get_dword();
108 qword = (qword << 32) + replay_get_dword();
109 }
110
111 return qword;
112}
113
114void replay_get_array(uint8_t *buf, size_t *size)
115{
116 if (replay_file) {
117 *size = replay_get_dword();
118 if (fread(buf, 1, *size, replay_file) != *size) {
119 error_report("replay read error");
120 }
121 }
122}
123
124void replay_get_array_alloc(uint8_t **buf, size_t *size)
125{
126 if (replay_file) {
127 *size = replay_get_dword();
128 *buf = g_malloc(*size);
129 if (fread(*buf, 1, *size, replay_file) != *size) {
130 error_report("replay read error");
131 }
132 }
133}
134
135void replay_check_error(void)
136{
137 if (replay_file) {
138 if (feof(replay_file)) {
139 error_report("replay file is over");
140 qemu_system_vmstop_request_prepare();
141 qemu_system_vmstop_request(RUN_STATE_PAUSED);
142 } else if (ferror(replay_file)) {
143 error_report("replay file is over or something goes wrong");
144 qemu_system_vmstop_request_prepare();
145 qemu_system_vmstop_request(RUN_STATE_INTERNAL_ERROR);
146 }
147 }
148}
149
150void replay_fetch_data_kind(void)
151{
152 if (replay_file) {
153 if (!replay_has_unread_data) {
154 replay_data_kind = replay_get_byte();
26bc60ac
PD
155 if (replay_data_kind == EVENT_INSTRUCTION) {
156 replay_state.instructions_count = replay_get_dword();
157 }
c92079f4
PD
158 replay_check_error();
159 replay_has_unread_data = 1;
26bc60ac
PD
160 if (replay_data_kind >= EVENT_COUNT) {
161 error_report("Replay: unknown event kind %d", replay_data_kind);
162 exit(1);
163 }
c92079f4
PD
164 }
165 }
166}
167
168void replay_finish_event(void)
169{
170 replay_has_unread_data = 0;
171 replay_fetch_data_kind();
172}
c16861ef
PD
173
174void replay_mutex_init(void)
175{
176 qemu_mutex_init(&lock);
177}
178
179void replay_mutex_destroy(void)
180{
181 qemu_mutex_destroy(&lock);
182}
183
184void replay_mutex_lock(void)
185{
186 qemu_mutex_lock(&lock);
187}
188
189void replay_mutex_unlock(void)
190{
191 qemu_mutex_unlock(&lock);
192}
26bc60ac
PD
193
194/*! Saves cached instructions. */
195void replay_save_instructions(void)
196{
197 if (replay_file && replay_mode == REPLAY_MODE_RECORD) {
198 replay_mutex_lock();
199 int diff = (int)(replay_get_current_step() - replay_state.current_step);
200 if (diff > 0) {
201 replay_put_event(EVENT_INSTRUCTION);
202 replay_put_dword(diff);
203 replay_state.current_step += diff;
204 }
205 replay_mutex_unlock();
206 }
207}