replay: flush rr queue before loading the vmstate
[qemu/ar7.git] / replay / replay-debugging.c
blobe1fe6b8661338ead77a9c5fbc24cab7aa8b213f6
1 /*
2 * replay-debugging.c
4 * Copyright (c) 2010-2020 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/osdep.h"
13 #include "qapi/error.h"
14 #include "sysemu/replay.h"
15 #include "sysemu/runstate.h"
16 #include "replay-internal.h"
17 #include "monitor/hmp.h"
18 #include "monitor/monitor.h"
19 #include "qapi/qapi-commands-replay.h"
20 #include "qapi/qmp/qdict.h"
21 #include "qemu/timer.h"
22 #include "block/snapshot.h"
23 #include "migration/snapshot.h"
25 void hmp_info_replay(Monitor *mon, const QDict *qdict)
27 if (replay_mode == REPLAY_MODE_NONE) {
28 monitor_printf(mon, "Record/replay is not active\n");
29 } else {
30 monitor_printf(mon,
31 "%s execution '%s': instruction count = %"PRId64"\n",
32 replay_mode == REPLAY_MODE_RECORD ? "Recording" : "Replaying",
33 replay_get_filename(), replay_get_current_icount());
37 ReplayInfo *qmp_query_replay(Error **errp)
39 ReplayInfo *retval = g_new0(ReplayInfo, 1);
41 retval->mode = replay_mode;
42 if (replay_get_filename()) {
43 retval->filename = g_strdup(replay_get_filename());
44 retval->has_filename = true;
46 retval->icount = replay_get_current_icount();
47 return retval;
50 static void replay_break(uint64_t icount, QEMUTimerCB callback, void *opaque)
52 assert(replay_mode == REPLAY_MODE_PLAY);
53 assert(replay_mutex_locked());
54 assert(replay_break_icount >= replay_get_current_icount());
55 assert(callback);
57 replay_break_icount = icount;
59 if (replay_break_timer) {
60 timer_del(replay_break_timer);
62 replay_break_timer = timer_new_ns(QEMU_CLOCK_REALTIME,
63 callback, opaque);
66 static void replay_delete_break(void)
68 assert(replay_mode == REPLAY_MODE_PLAY);
69 assert(replay_mutex_locked());
71 if (replay_break_timer) {
72 timer_del(replay_break_timer);
73 timer_free(replay_break_timer);
74 replay_break_timer = NULL;
76 replay_break_icount = -1ULL;
79 static void replay_stop_vm(void *opaque)
81 vm_stop(RUN_STATE_PAUSED);
82 replay_delete_break();
85 void qmp_replay_break(int64_t icount, Error **errp)
87 if (replay_mode == REPLAY_MODE_PLAY) {
88 if (icount >= replay_get_current_icount()) {
89 replay_break(icount, replay_stop_vm, NULL);
90 } else {
91 error_setg(errp,
92 "cannot set breakpoint at the instruction in the past");
94 } else {
95 error_setg(errp, "setting the breakpoint is allowed only in play mode");
99 void hmp_replay_break(Monitor *mon, const QDict *qdict)
101 int64_t icount = qdict_get_try_int(qdict, "icount", -1LL);
102 Error *err = NULL;
104 qmp_replay_break(icount, &err);
105 if (err) {
106 error_report_err(err);
107 return;
111 void qmp_replay_delete_break(Error **errp)
113 if (replay_mode == REPLAY_MODE_PLAY) {
114 replay_delete_break();
115 } else {
116 error_setg(errp, "replay breakpoints are allowed only in play mode");
120 void hmp_replay_delete_break(Monitor *mon, const QDict *qdict)
122 Error *err = NULL;
124 qmp_replay_delete_break(&err);
125 if (err) {
126 error_report_err(err);
127 return;
131 static char *replay_find_nearest_snapshot(int64_t icount,
132 int64_t *snapshot_icount)
134 BlockDriverState *bs;
135 QEMUSnapshotInfo *sn_tab;
136 QEMUSnapshotInfo *nearest = NULL;
137 char *ret = NULL;
138 int nb_sns, i;
139 AioContext *aio_context;
141 *snapshot_icount = -1;
143 bs = bdrv_all_find_vmstate_bs();
144 if (!bs) {
145 goto fail;
147 aio_context = bdrv_get_aio_context(bs);
149 aio_context_acquire(aio_context);
150 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
151 aio_context_release(aio_context);
153 for (i = 0; i < nb_sns; i++) {
154 if (bdrv_all_find_snapshot(sn_tab[i].name, &bs) == 0) {
155 if (sn_tab[i].icount != -1ULL
156 && sn_tab[i].icount <= icount
157 && (!nearest || nearest->icount < sn_tab[i].icount)) {
158 nearest = &sn_tab[i];
162 if (nearest) {
163 ret = g_strdup(nearest->name);
164 *snapshot_icount = nearest->icount;
166 g_free(sn_tab);
168 fail:
169 return ret;
172 static void replay_seek(int64_t icount, QEMUTimerCB callback, Error **errp)
174 char *snapshot = NULL;
175 int64_t snapshot_icount;
177 if (replay_mode != REPLAY_MODE_PLAY) {
178 error_setg(errp, "replay must be enabled to seek");
179 return;
182 snapshot = replay_find_nearest_snapshot(icount, &snapshot_icount);
183 if (snapshot) {
184 if (icount < replay_get_current_icount()
185 || replay_get_current_icount() < snapshot_icount) {
186 vm_stop(RUN_STATE_RESTORE_VM);
187 load_snapshot(snapshot, errp);
189 g_free(snapshot);
191 if (replay_get_current_icount() <= icount) {
192 replay_break(icount, callback, NULL);
193 vm_start();
194 } else {
195 error_setg(errp, "cannot seek to the specified instruction count");
199 void qmp_replay_seek(int64_t icount, Error **errp)
201 replay_seek(icount, replay_stop_vm, errp);
204 void hmp_replay_seek(Monitor *mon, const QDict *qdict)
206 int64_t icount = qdict_get_try_int(qdict, "icount", -1LL);
207 Error *err = NULL;
209 qmp_replay_seek(icount, &err);
210 if (err) {
211 error_report_err(err);
212 return;