]>
Commit | Line | Data |
---|---|---|
306e196f PD |
1 | /* |
2 | * replay-snapshot.c | |
3 | * | |
4 | * Copyright (c) 2010-2016 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 | ||
12 | #include "qemu/osdep.h" | |
13 | #include "qapi/error.h" | |
306e196f PD |
14 | #include "sysemu/replay.h" |
15 | #include "replay-internal.h" | |
306e196f PD |
16 | #include "monitor/monitor.h" |
17 | #include "qapi/qmp/qstring.h" | |
18 | #include "qemu/error-report.h" | |
19 | #include "migration/vmstate.h" | |
5e22479a | 20 | #include "migration/snapshot.h" |
306e196f | 21 | |
44b1ff31 | 22 | static int replay_pre_save(void *opaque) |
306e196f PD |
23 | { |
24 | ReplayState *state = opaque; | |
25 | state->file_offset = ftell(replay_file); | |
4b930d26 | 26 | state->host_clock_last = qemu_clock_get_last(QEMU_CLOCK_HOST); |
44b1ff31 DDAG |
27 | |
28 | return 0; | |
306e196f PD |
29 | } |
30 | ||
31 | static int replay_post_load(void *opaque, int version_id) | |
32 | { | |
33 | ReplayState *state = opaque; | |
bb3d7702 PD |
34 | if (replay_mode == REPLAY_MODE_PLAY) { |
35 | fseek(replay_file, state->file_offset, SEEK_SET); | |
36 | qemu_clock_set_last(QEMU_CLOCK_HOST, state->host_clock_last); | |
37 | /* If this was a vmstate, saved in recording mode, | |
38 | we need to initialize replay data fields. */ | |
39 | replay_fetch_data_kind(); | |
40 | } else if (replay_mode == REPLAY_MODE_RECORD) { | |
41 | /* This is only useful for loading the initial state. | |
42 | Therefore reset all the counters. */ | |
43 | state->instructions_count = 0; | |
44 | state->block_request_id = 0; | |
45 | } | |
306e196f PD |
46 | |
47 | return 0; | |
48 | } | |
49 | ||
50 | static const VMStateDescription vmstate_replay = { | |
51 | .name = "replay", | |
52 | .version_id = 1, | |
53 | .minimum_version_id = 1, | |
54 | .pre_save = replay_pre_save, | |
55 | .post_load = replay_post_load, | |
56 | .fields = (VMStateField[]) { | |
57 | VMSTATE_INT64_ARRAY(cached_clock, ReplayState, REPLAY_CLOCK_COUNT), | |
58 | VMSTATE_UINT64(current_step, ReplayState), | |
59 | VMSTATE_INT32(instructions_count, ReplayState), | |
60 | VMSTATE_UINT32(data_kind, ReplayState), | |
61 | VMSTATE_UINT32(has_unread_data, ReplayState), | |
62 | VMSTATE_UINT64(file_offset, ReplayState), | |
6d0ceb80 | 63 | VMSTATE_UINT64(block_request_id, ReplayState), |
4b930d26 | 64 | VMSTATE_UINT64(host_clock_last, ReplayState), |
0b30dc01 PD |
65 | VMSTATE_INT32(read_event_kind, ReplayState), |
66 | VMSTATE_UINT64(read_event_id, ReplayState), | |
67 | VMSTATE_INT32(read_event_checkpoint, ReplayState), | |
306e196f PD |
68 | VMSTATE_END_OF_LIST() |
69 | }, | |
70 | }; | |
71 | ||
72 | void replay_vmstate_register(void) | |
73 | { | |
74 | vmstate_register(NULL, 0, &vmstate_replay, &replay_state); | |
75 | } | |
9c2037d0 PD |
76 | |
77 | void replay_vmstate_init(void) | |
78 | { | |
927d6638 JQ |
79 | Error *err = NULL; |
80 | ||
9c2037d0 PD |
81 | if (replay_snapshot) { |
82 | if (replay_mode == REPLAY_MODE_RECORD) { | |
5e22479a | 83 | if (save_snapshot(replay_snapshot, &err) != 0) { |
927d6638 | 84 | error_report_err(err); |
9c2037d0 PD |
85 | error_report("Could not create snapshot for icount record"); |
86 | exit(1); | |
87 | } | |
88 | } else if (replay_mode == REPLAY_MODE_PLAY) { | |
5e22479a | 89 | if (load_snapshot(replay_snapshot, &err) != 0) { |
927d6638 | 90 | error_report_err(err); |
9c2037d0 PD |
91 | error_report("Could not load snapshot for icount replay"); |
92 | exit(1); | |
93 | } | |
94 | } | |
95 | } | |
96 | } | |
377b21cc PD |
97 | |
98 | bool replay_can_snapshot(void) | |
99 | { | |
100 | return replay_mode == REPLAY_MODE_NONE | |
101 | || !replay_has_events(); | |
102 | } |