| 1 | #ifndef REPLAY_INTERNAL_H |
| 2 | #define REPLAY_INTERNAL_H |
| 3 | |
| 4 | /* |
| 5 | * replay-internal.h |
| 6 | * |
| 7 | * Copyright (c) 2010-2015 Institute for System Programming |
| 8 | * of the Russian Academy of Sciences. |
| 9 | * |
| 10 | * This work is licensed under the terms of the GNU GPL, version 2 or later. |
| 11 | * See the COPYING file in the top-level directory. |
| 12 | * |
| 13 | */ |
| 14 | |
| 15 | /* Asynchronous events IDs */ |
| 16 | |
| 17 | typedef enum ReplayAsyncEventKind { |
| 18 | REPLAY_ASYNC_EVENT_BH, |
| 19 | REPLAY_ASYNC_EVENT_BH_ONESHOT, |
| 20 | REPLAY_ASYNC_EVENT_INPUT, |
| 21 | REPLAY_ASYNC_EVENT_INPUT_SYNC, |
| 22 | REPLAY_ASYNC_EVENT_CHAR_READ, |
| 23 | REPLAY_ASYNC_EVENT_BLOCK, |
| 24 | REPLAY_ASYNC_EVENT_NET, |
| 25 | REPLAY_ASYNC_COUNT |
| 26 | } ReplayAsyncEventKind; |
| 27 | |
| 28 | /* |
| 29 | * Any changes to order/number of events will need to bump |
| 30 | * REPLAY_VERSION to prevent confusion with old logs. Also don't |
| 31 | * forget to update replay_event_name() to make your debugging life |
| 32 | * easier. |
| 33 | */ |
| 34 | enum ReplayEvents { |
| 35 | /* for instruction event */ |
| 36 | EVENT_INSTRUCTION, |
| 37 | /* for software interrupt */ |
| 38 | EVENT_INTERRUPT, |
| 39 | /* for emulated exceptions */ |
| 40 | EVENT_EXCEPTION, |
| 41 | /* for async events */ |
| 42 | EVENT_ASYNC, |
| 43 | EVENT_ASYNC_LAST = EVENT_ASYNC + REPLAY_ASYNC_COUNT - 1, |
| 44 | /* for shutdown requests, range allows recovery of ShutdownCause */ |
| 45 | EVENT_SHUTDOWN, |
| 46 | EVENT_SHUTDOWN_LAST = EVENT_SHUTDOWN + SHUTDOWN_CAUSE__MAX, |
| 47 | /* for character device write event */ |
| 48 | EVENT_CHAR_WRITE, |
| 49 | /* for character device read all event */ |
| 50 | EVENT_CHAR_READ_ALL, |
| 51 | EVENT_CHAR_READ_ALL_ERROR, |
| 52 | /* for audio out event */ |
| 53 | EVENT_AUDIO_OUT, |
| 54 | /* for audio in event */ |
| 55 | EVENT_AUDIO_IN, |
| 56 | /* for random number generator */ |
| 57 | EVENT_RANDOM, |
| 58 | /* for clock read/writes */ |
| 59 | /* some of greater codes are reserved for clocks */ |
| 60 | EVENT_CLOCK, |
| 61 | EVENT_CLOCK_LAST = EVENT_CLOCK + REPLAY_CLOCK_COUNT - 1, |
| 62 | /* for checkpoint event */ |
| 63 | /* some of greater codes are reserved for checkpoints */ |
| 64 | EVENT_CHECKPOINT, |
| 65 | EVENT_CHECKPOINT_LAST = EVENT_CHECKPOINT + CHECKPOINT_COUNT - 1, |
| 66 | /* end of log event */ |
| 67 | EVENT_END, |
| 68 | EVENT_COUNT |
| 69 | }; |
| 70 | |
| 71 | /** |
| 72 | * typedef ReplayState - global tracking Replay state |
| 73 | * |
| 74 | * This structure tracks where we are in the current ReplayState |
| 75 | * including the logged events from the recorded replay stream. Some |
| 76 | * of the data is also stored/restored from VMStateDescription when VM |
| 77 | * save/restore events take place. |
| 78 | * |
| 79 | * @cached_clock: Cached clocks values |
| 80 | * @current_icount: number of processed instructions |
| 81 | * @instruction_count: number of instructions until next event |
| 82 | * @current_event: current event index |
| 83 | * @data_kind: current event |
| 84 | * @has_unread_data: true if event not yet processed |
| 85 | * @file_offset: offset into replay log at replay snapshot |
| 86 | * @block_request_id: current serialised block request id |
| 87 | * @read_event_id: current async read event id |
| 88 | * @n_audio_samples: expected audio samples |
| 89 | */ |
| 90 | typedef struct ReplayState { |
| 91 | int64_t cached_clock[REPLAY_CLOCK_COUNT]; |
| 92 | uint64_t current_icount; |
| 93 | int instruction_count; |
| 94 | unsigned int current_event; |
| 95 | unsigned int data_kind; |
| 96 | bool has_unread_data; |
| 97 | uint64_t file_offset; |
| 98 | uint64_t block_request_id; |
| 99 | uint64_t read_event_id; |
| 100 | size_t n_audio_samples; |
| 101 | } ReplayState; |
| 102 | extern ReplayState replay_state; |
| 103 | |
| 104 | /* File for replay writing */ |
| 105 | extern FILE *replay_file; |
| 106 | /* Instruction count of the replay breakpoint */ |
| 107 | extern uint64_t replay_break_icount; |
| 108 | /* Timer for the replay breakpoint callback */ |
| 109 | extern QEMUTimer *replay_break_timer; |
| 110 | |
| 111 | void replay_put_byte(uint8_t byte); |
| 112 | void replay_put_event(uint8_t event); |
| 113 | void replay_put_word(uint16_t word); |
| 114 | void replay_put_dword(uint32_t dword); |
| 115 | void replay_put_qword(int64_t qword); |
| 116 | void replay_put_array(const uint8_t *buf, size_t size); |
| 117 | |
| 118 | uint8_t replay_get_byte(void); |
| 119 | uint16_t replay_get_word(void); |
| 120 | uint32_t replay_get_dword(void); |
| 121 | int64_t replay_get_qword(void); |
| 122 | void replay_get_array(uint8_t *buf, size_t *size); |
| 123 | void replay_get_array_alloc(uint8_t **buf, size_t *size); |
| 124 | |
| 125 | /* Mutex functions for protecting replay log file and ensuring |
| 126 | * synchronisation between vCPU and main-loop threads. */ |
| 127 | |
| 128 | void replay_mutex_init(void); |
| 129 | bool replay_mutex_locked(void); |
| 130 | |
| 131 | /*! Checks error status of the file. */ |
| 132 | void replay_check_error(void); |
| 133 | |
| 134 | /*! Finishes processing of the replayed event and fetches |
| 135 | the next event from the log. */ |
| 136 | void replay_finish_event(void); |
| 137 | /*! Reads data type from the file and stores it in the |
| 138 | data_kind variable. */ |
| 139 | void replay_fetch_data_kind(void); |
| 140 | |
| 141 | /*! Advance replay_state.current_icount to the specified value. */ |
| 142 | void replay_advance_current_icount(uint64_t current_icount); |
| 143 | /*! Saves queued events (like instructions and sound). */ |
| 144 | void replay_save_instructions(void); |
| 145 | |
| 146 | /*! Skips async events until some sync event will be found. |
| 147 | \return true, if event was found */ |
| 148 | bool replay_next_event_is(int event); |
| 149 | |
| 150 | /*! Reads next clock value from the file. |
| 151 | If clock kind read from the file is different from the parameter, |
| 152 | the value is not used. */ |
| 153 | void replay_read_next_clock(ReplayClockKind kind); |
| 154 | |
| 155 | /* Asynchronous events queue */ |
| 156 | |
| 157 | /*! Initializes events' processing internals */ |
| 158 | void replay_init_events(void); |
| 159 | /*! Clears internal data structures for events handling */ |
| 160 | void replay_finish_events(void); |
| 161 | /*! Returns true if there are any unsaved events in the queue */ |
| 162 | bool replay_has_events(void); |
| 163 | /*! Saves events from queue into the file */ |
| 164 | void replay_save_events(void); |
| 165 | /*! Read events from the file into the input queue */ |
| 166 | void replay_read_events(void); |
| 167 | /*! Adds specified async event to the queue */ |
| 168 | void replay_add_event(ReplayAsyncEventKind event_kind, void *opaque, |
| 169 | void *opaque2, uint64_t id); |
| 170 | |
| 171 | /* Input events */ |
| 172 | |
| 173 | /*! Saves input event to the log */ |
| 174 | void replay_save_input_event(QemuInputEvent *evt); |
| 175 | /*! Reads input event from the log */ |
| 176 | QemuInputEvent *replay_read_input_event(void); |
| 177 | /*! Adds input event to the queue */ |
| 178 | void replay_add_input_event(QemuInputEvent *event); |
| 179 | /*! Adds input sync event to the queue */ |
| 180 | void replay_add_input_sync_event(void); |
| 181 | |
| 182 | /* Character devices */ |
| 183 | |
| 184 | /*! Called to run char device read event. */ |
| 185 | void replay_event_char_read_run(void *opaque); |
| 186 | /*! Writes char read event to the file. */ |
| 187 | void replay_event_char_read_save(void *opaque); |
| 188 | /*! Reads char event read from the file. */ |
| 189 | void *replay_event_char_read_load(void); |
| 190 | |
| 191 | /* Network devices */ |
| 192 | |
| 193 | /*! Called to run network event. */ |
| 194 | void replay_event_net_run(void *opaque); |
| 195 | /*! Writes network event to the file. */ |
| 196 | void replay_event_net_save(void *opaque); |
| 197 | /*! Reads network from the file. */ |
| 198 | void *replay_event_net_load(void); |
| 199 | |
| 200 | /* Diagnostics */ |
| 201 | |
| 202 | /** |
| 203 | * replay_sync_error(): report sync error and exit |
| 204 | * |
| 205 | * When we reach an error condition we want to report it centrally so |
| 206 | * we can also dump some useful information into the logs. |
| 207 | */ |
| 208 | G_NORETURN void replay_sync_error(const char *error); |
| 209 | |
| 210 | /* VMState-related functions */ |
| 211 | |
| 212 | /* Registers replay VMState. |
| 213 | Should be called before virtual devices initialization |
| 214 | to make cached timers available for post_load functions. */ |
| 215 | void replay_vmstate_register(void); |
| 216 | |
| 217 | #endif |