mirror of
https://github.com/qemu/qemu.git
synced 2024-11-26 12:23:36 +08:00
377b21ccea
This patch does not allows saving/loading vmstate when replay events queue is not empty. There is no reliable way to save events queue, because it describes internal coroutine state. Therefore saving and loading operations should be deferred to another record/replay step. Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru> Message-Id: <20180227095214.1060.32939.stgit@pasha-VirtualBox> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
92 lines
2.5 KiB
C
92 lines
2.5 KiB
C
/*
|
|
* replay-snapshot.c
|
|
*
|
|
* Copyright (c) 2010-2016 Institute for System Programming
|
|
* of the Russian Academy of Sciences.
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
* See the COPYING file in the top-level directory.
|
|
*
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qapi/error.h"
|
|
#include "qemu-common.h"
|
|
#include "sysemu/replay.h"
|
|
#include "replay-internal.h"
|
|
#include "sysemu/sysemu.h"
|
|
#include "monitor/monitor.h"
|
|
#include "qapi/qmp/qstring.h"
|
|
#include "qemu/error-report.h"
|
|
#include "migration/vmstate.h"
|
|
#include "migration/snapshot.h"
|
|
|
|
static int replay_pre_save(void *opaque)
|
|
{
|
|
ReplayState *state = opaque;
|
|
state->file_offset = ftell(replay_file);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int replay_post_load(void *opaque, int version_id)
|
|
{
|
|
ReplayState *state = opaque;
|
|
fseek(replay_file, state->file_offset, SEEK_SET);
|
|
/* If this was a vmstate, saved in recording mode,
|
|
we need to initialize replay data fields. */
|
|
replay_fetch_data_kind();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const VMStateDescription vmstate_replay = {
|
|
.name = "replay",
|
|
.version_id = 1,
|
|
.minimum_version_id = 1,
|
|
.pre_save = replay_pre_save,
|
|
.post_load = replay_post_load,
|
|
.fields = (VMStateField[]) {
|
|
VMSTATE_INT64_ARRAY(cached_clock, ReplayState, REPLAY_CLOCK_COUNT),
|
|
VMSTATE_UINT64(current_step, ReplayState),
|
|
VMSTATE_INT32(instructions_count, ReplayState),
|
|
VMSTATE_UINT32(data_kind, ReplayState),
|
|
VMSTATE_UINT32(has_unread_data, ReplayState),
|
|
VMSTATE_UINT64(file_offset, ReplayState),
|
|
VMSTATE_UINT64(block_request_id, ReplayState),
|
|
VMSTATE_END_OF_LIST()
|
|
},
|
|
};
|
|
|
|
void replay_vmstate_register(void)
|
|
{
|
|
vmstate_register(NULL, 0, &vmstate_replay, &replay_state);
|
|
}
|
|
|
|
void replay_vmstate_init(void)
|
|
{
|
|
Error *err = NULL;
|
|
|
|
if (replay_snapshot) {
|
|
if (replay_mode == REPLAY_MODE_RECORD) {
|
|
if (save_snapshot(replay_snapshot, &err) != 0) {
|
|
error_report_err(err);
|
|
error_report("Could not create snapshot for icount record");
|
|
exit(1);
|
|
}
|
|
} else if (replay_mode == REPLAY_MODE_PLAY) {
|
|
if (load_snapshot(replay_snapshot, &err) != 0) {
|
|
error_report_err(err);
|
|
error_report("Could not load snapshot for icount replay");
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool replay_can_snapshot(void)
|
|
{
|
|
return replay_mode == REPLAY_MODE_NONE
|
|
|| !replay_has_events();
|
|
}
|