12
#include "qemu/osdep.h"
13
#include "qemu/error-report.h"
14
#include "sysemu/replay.h"
15
#include "replay-internal.h"
18
#include "hw/core/cpu.h"
21
ReplayAsyncEventKind event_kind;
26
QTAILQ_ENTRY(Event) events;
29
static QTAILQ_HEAD(, Event) events_list = QTAILQ_HEAD_INITIALIZER(events_list);
30
static bool events_enabled;
34
static void replay_run_event(Event *event)
36
switch (event->event_kind) {
37
case REPLAY_ASYNC_EVENT_BH:
38
aio_bh_call(event->opaque);
40
case REPLAY_ASYNC_EVENT_BH_ONESHOT:
41
((QEMUBHFunc *)event->opaque)(event->opaque2);
43
case REPLAY_ASYNC_EVENT_INPUT:
44
qemu_input_event_send_impl(NULL, (InputEvent *)event->opaque);
45
qapi_free_InputEvent((InputEvent *)event->opaque);
47
case REPLAY_ASYNC_EVENT_INPUT_SYNC:
48
qemu_input_event_sync_impl();
50
case REPLAY_ASYNC_EVENT_CHAR_READ:
51
replay_event_char_read_run(event->opaque);
53
case REPLAY_ASYNC_EVENT_BLOCK:
54
aio_bh_call(event->opaque);
56
case REPLAY_ASYNC_EVENT_NET:
57
replay_event_net_run(event->opaque);
60
error_report("Replay: invalid async event ID (%d) in the queue",
67
void replay_enable_events(void)
69
if (replay_mode != REPLAY_MODE_NONE) {
70
events_enabled = true;
74
bool replay_has_events(void)
76
return !QTAILQ_EMPTY(&events_list);
79
void replay_flush_events(void)
81
if (replay_mode == REPLAY_MODE_NONE) {
85
g_assert(replay_mutex_locked());
87
while (!QTAILQ_EMPTY(&events_list)) {
88
Event *event = QTAILQ_FIRST(&events_list);
89
replay_run_event(event);
90
QTAILQ_REMOVE(&events_list, event, events);
95
void replay_disable_events(void)
97
if (replay_mode != REPLAY_MODE_NONE) {
98
events_enabled = false;
100
replay_flush_events();
105
void replay_add_event(ReplayAsyncEventKind event_kind,
107
void *opaque2, uint64_t id)
109
assert(event_kind < REPLAY_ASYNC_COUNT);
111
if (!replay_file || replay_mode == REPLAY_MODE_NONE
112
|| !events_enabled) {
114
e.event_kind = event_kind;
118
replay_run_event(&e);
122
Event *event = g_new0(Event, 1);
123
event->event_kind = event_kind;
124
event->opaque = opaque;
125
event->opaque2 = opaque2;
128
g_assert(replay_mutex_locked());
129
QTAILQ_INSERT_TAIL(&events_list, event, events);
130
qemu_cpu_kick(first_cpu);
133
void replay_bh_schedule_event(QEMUBH *bh)
135
if (events_enabled) {
136
uint64_t id = replay_get_current_icount();
137
replay_add_event(REPLAY_ASYNC_EVENT_BH, bh, NULL, id);
139
qemu_bh_schedule(bh);
143
void replay_bh_schedule_oneshot_event(AioContext *ctx,
144
QEMUBHFunc *cb, void *opaque)
146
if (events_enabled) {
147
uint64_t id = replay_get_current_icount();
148
replay_add_event(REPLAY_ASYNC_EVENT_BH_ONESHOT, cb, opaque, id);
150
aio_bh_schedule_oneshot(ctx, cb, opaque);
154
void replay_add_input_event(struct InputEvent *event)
156
replay_add_event(REPLAY_ASYNC_EVENT_INPUT, event, NULL, 0);
159
void replay_add_input_sync_event(void)
161
replay_add_event(REPLAY_ASYNC_EVENT_INPUT_SYNC, NULL, NULL, 0);
164
void replay_block_event(QEMUBH *bh, uint64_t id)
166
if (events_enabled) {
167
replay_add_event(REPLAY_ASYNC_EVENT_BLOCK, bh, NULL, id);
169
qemu_bh_schedule(bh);
173
static void replay_save_event(Event *event)
175
if (replay_mode != REPLAY_MODE_PLAY) {
177
g_assert(event->event_kind < REPLAY_ASYNC_COUNT);
178
replay_put_event(EVENT_ASYNC + event->event_kind);
181
switch (event->event_kind) {
182
case REPLAY_ASYNC_EVENT_BH:
183
case REPLAY_ASYNC_EVENT_BH_ONESHOT:
184
replay_put_qword(event->id);
186
case REPLAY_ASYNC_EVENT_INPUT:
187
replay_save_input_event(event->opaque);
189
case REPLAY_ASYNC_EVENT_INPUT_SYNC:
191
case REPLAY_ASYNC_EVENT_CHAR_READ:
192
replay_event_char_read_save(event->opaque);
194
case REPLAY_ASYNC_EVENT_BLOCK:
195
replay_put_qword(event->id);
197
case REPLAY_ASYNC_EVENT_NET:
198
replay_event_net_save(event->opaque);
201
error_report("Unknown ID %" PRId64 " of replay event", event->id);
208
void replay_save_events(void)
210
g_assert(replay_mutex_locked());
211
while (!QTAILQ_EMPTY(&events_list)) {
212
Event *event = QTAILQ_FIRST(&events_list);
213
replay_save_event(event);
214
replay_run_event(event);
215
QTAILQ_REMOVE(&events_list, event, events);
220
static Event *replay_read_event(void)
223
ReplayAsyncEventKind event_kind = replay_state.data_kind - EVENT_ASYNC;
226
switch (event_kind) {
227
case REPLAY_ASYNC_EVENT_BH:
228
case REPLAY_ASYNC_EVENT_BH_ONESHOT:
229
if (replay_state.read_event_id == -1) {
230
replay_state.read_event_id = replay_get_qword();
233
case REPLAY_ASYNC_EVENT_INPUT:
234
event = g_new0(Event, 1);
235
event->event_kind = event_kind;
236
event->opaque = replay_read_input_event();
238
case REPLAY_ASYNC_EVENT_INPUT_SYNC:
239
event = g_new0(Event, 1);
240
event->event_kind = event_kind;
243
case REPLAY_ASYNC_EVENT_CHAR_READ:
244
event = g_new0(Event, 1);
245
event->event_kind = event_kind;
246
event->opaque = replay_event_char_read_load();
248
case REPLAY_ASYNC_EVENT_BLOCK:
249
if (replay_state.read_event_id == -1) {
250
replay_state.read_event_id = replay_get_qword();
253
case REPLAY_ASYNC_EVENT_NET:
254
event = g_new0(Event, 1);
255
event->event_kind = event_kind;
256
event->opaque = replay_event_net_load();
259
error_report("Unknown ID %d of replay event", event_kind);
264
QTAILQ_FOREACH(event, &events_list, events) {
265
if (event->event_kind == event_kind
266
&& (replay_state.read_event_id == -1
267
|| replay_state.read_event_id == event->id)) {
273
QTAILQ_REMOVE(&events_list, event, events);
280
void replay_read_events(void)
282
g_assert(replay_mutex_locked());
283
while (replay_state.data_kind >= EVENT_ASYNC
284
&& replay_state.data_kind <= EVENT_ASYNC_LAST) {
285
Event *event = replay_read_event();
289
replay_finish_event();
290
replay_state.read_event_id = -1;
291
replay_run_event(event);
297
void replay_init_events(void)
299
replay_state.read_event_id = -1;
302
void replay_finish_events(void)
304
events_enabled = false;
305
replay_flush_events();
308
bool replay_events_enabled(void)
310
return events_enabled;
313
uint64_t blkreplay_next_id(void)
315
if (replay_events_enabled()) {
316
return replay_state.block_request_id++;