1 /* 2 * replay.c 3 * 4 * Copyright (c) 2010-2015 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" 14 #include "qemu-common.h" 15 #include "sysemu/replay.h" 16 #include "replay-internal.h" 17 #include "qemu/timer.h" 18 #include "qemu/main-loop.h" 19 #include "sysemu/sysemu.h" 20 #include "qemu/error-report.h" 21 22 /* Current version of the replay mechanism. 23 Increase it when file format changes. */ 24 #define REPLAY_VERSION 0xe02005 25 /* Size of replay log header */ 26 #define HEADER_SIZE (sizeof(uint32_t) + sizeof(uint64_t)) 27 28 ReplayMode replay_mode = REPLAY_MODE_NONE; 29 30 /* Name of replay file */ 31 static char *replay_filename; 32 ReplayState replay_state; 33 static GSList *replay_blockers; 34 35 bool replay_next_event_is(int event) 36 { 37 bool res = false; 38 39 /* nothing to skip - not all instructions used */ 40 if (replay_state.instructions_count != 0) { 41 assert(replay_state.data_kind == EVENT_INSTRUCTION); 42 return event == EVENT_INSTRUCTION; 43 } 44 45 while (true) { 46 if (event == replay_state.data_kind) { 47 res = true; 48 } 49 switch (replay_state.data_kind) { 50 case EVENT_SHUTDOWN: 51 replay_finish_event(); 52 qemu_system_shutdown_request(); 53 break; 54 default: 55 /* clock, time_t, checkpoint and other events */ 56 return res; 57 } 58 } 59 return res; 60 } 61 62 uint64_t replay_get_current_step(void) 63 { 64 return cpu_get_icount_raw(); 65 } 66 67 int replay_get_instructions(void) 68 { 69 int res = 0; 70 replay_mutex_lock(); 71 if (replay_next_event_is(EVENT_INSTRUCTION)) { 72 res = replay_state.instructions_count; 73 } 74 replay_mutex_unlock(); 75 return res; 76 } 77 78 void replay_account_executed_instructions(void) 79 { 80 if (replay_mode == REPLAY_MODE_PLAY) { 81 replay_mutex_lock(); 82 if (replay_state.instructions_count > 0) { 83 int count = (int)(replay_get_current_step() 84 - replay_state.current_step); 85 replay_state.instructions_count -= count; 86 replay_state.current_step += count; 87 if (replay_state.instructions_count == 0) { 88 assert(replay_state.data_kind == EVENT_INSTRUCTION); 89 replay_finish_event(); 90 /* Wake up iothread. This is required because 91 timers will not expire until clock counters 92 will be read from the log. */ 93 qemu_notify_event(); 94 } 95 } 96 replay_mutex_unlock(); 97 } 98 } 99 100 bool replay_exception(void) 101 { 102 if (replay_mode == REPLAY_MODE_RECORD) { 103 replay_save_instructions(); 104 replay_mutex_lock(); 105 replay_put_event(EVENT_EXCEPTION); 106 replay_mutex_unlock(); 107 return true; 108 } else if (replay_mode == REPLAY_MODE_PLAY) { 109 bool res = replay_has_exception(); 110 if (res) { 111 replay_mutex_lock(); 112 replay_finish_event(); 113 replay_mutex_unlock(); 114 } 115 return res; 116 } 117 118 return true; 119 } 120 121 bool replay_has_exception(void) 122 { 123 bool res = false; 124 if (replay_mode == REPLAY_MODE_PLAY) { 125 replay_account_executed_instructions(); 126 replay_mutex_lock(); 127 res = replay_next_event_is(EVENT_EXCEPTION); 128 replay_mutex_unlock(); 129 } 130 131 return res; 132 } 133 134 bool replay_interrupt(void) 135 { 136 if (replay_mode == REPLAY_MODE_RECORD) { 137 replay_save_instructions(); 138 replay_mutex_lock(); 139 replay_put_event(EVENT_INTERRUPT); 140 replay_mutex_unlock(); 141 return true; 142 } else if (replay_mode == REPLAY_MODE_PLAY) { 143 bool res = replay_has_interrupt(); 144 if (res) { 145 replay_mutex_lock(); 146 replay_finish_event(); 147 replay_mutex_unlock(); 148 } 149 return res; 150 } 151 152 return true; 153 } 154 155 bool replay_has_interrupt(void) 156 { 157 bool res = false; 158 if (replay_mode == REPLAY_MODE_PLAY) { 159 replay_account_executed_instructions(); 160 replay_mutex_lock(); 161 res = replay_next_event_is(EVENT_INTERRUPT); 162 replay_mutex_unlock(); 163 } 164 return res; 165 } 166 167 void replay_shutdown_request(void) 168 { 169 if (replay_mode == REPLAY_MODE_RECORD) { 170 replay_mutex_lock(); 171 replay_put_event(EVENT_SHUTDOWN); 172 replay_mutex_unlock(); 173 } 174 } 175 176 bool replay_checkpoint(ReplayCheckpoint checkpoint) 177 { 178 bool res = false; 179 assert(EVENT_CHECKPOINT + checkpoint <= EVENT_CHECKPOINT_LAST); 180 replay_save_instructions(); 181 182 if (!replay_file) { 183 return true; 184 } 185 186 replay_mutex_lock(); 187 188 if (replay_mode == REPLAY_MODE_PLAY) { 189 if (replay_next_event_is(EVENT_CHECKPOINT + checkpoint)) { 190 replay_finish_event(); 191 } else if (replay_state.data_kind != EVENT_ASYNC) { 192 res = false; 193 goto out; 194 } 195 replay_read_events(checkpoint); 196 /* replay_read_events may leave some unread events. 197 Return false if not all of the events associated with 198 checkpoint were processed */ 199 res = replay_state.data_kind != EVENT_ASYNC; 200 } else if (replay_mode == REPLAY_MODE_RECORD) { 201 replay_put_event(EVENT_CHECKPOINT + checkpoint); 202 replay_save_events(checkpoint); 203 res = true; 204 } 205 out: 206 replay_mutex_unlock(); 207 return res; 208 } 209 210 static void replay_enable(const char *fname, int mode) 211 { 212 const char *fmode = NULL; 213 assert(!replay_file); 214 215 switch (mode) { 216 case REPLAY_MODE_RECORD: 217 fmode = "wb"; 218 break; 219 case REPLAY_MODE_PLAY: 220 fmode = "rb"; 221 break; 222 default: 223 fprintf(stderr, "Replay: internal error: invalid replay mode\n"); 224 exit(1); 225 } 226 227 atexit(replay_finish); 228 229 replay_mutex_init(); 230 231 replay_file = fopen(fname, fmode); 232 if (replay_file == NULL) { 233 fprintf(stderr, "Replay: open %s: %s\n", fname, strerror(errno)); 234 exit(1); 235 } 236 237 replay_filename = g_strdup(fname); 238 239 replay_mode = mode; 240 replay_state.data_kind = -1; 241 replay_state.instructions_count = 0; 242 replay_state.current_step = 0; 243 replay_state.has_unread_data = 0; 244 245 /* skip file header for RECORD and check it for PLAY */ 246 if (replay_mode == REPLAY_MODE_RECORD) { 247 fseek(replay_file, HEADER_SIZE, SEEK_SET); 248 } else if (replay_mode == REPLAY_MODE_PLAY) { 249 unsigned int version = replay_get_dword(); 250 if (version != REPLAY_VERSION) { 251 fprintf(stderr, "Replay: invalid input log file version\n"); 252 exit(1); 253 } 254 /* go to the beginning */ 255 fseek(replay_file, HEADER_SIZE, SEEK_SET); 256 replay_fetch_data_kind(); 257 } 258 259 replay_init_events(); 260 } 261 262 void replay_configure(QemuOpts *opts) 263 { 264 const char *fname; 265 const char *rr; 266 ReplayMode mode = REPLAY_MODE_NONE; 267 Location loc; 268 269 if (!opts) { 270 return; 271 } 272 273 loc_push_none(&loc); 274 qemu_opts_loc_restore(opts); 275 276 rr = qemu_opt_get(opts, "rr"); 277 if (!rr) { 278 /* Just enabling icount */ 279 goto out; 280 } else if (!strcmp(rr, "record")) { 281 mode = REPLAY_MODE_RECORD; 282 } else if (!strcmp(rr, "replay")) { 283 mode = REPLAY_MODE_PLAY; 284 } else { 285 error_report("Invalid icount rr option: %s", rr); 286 exit(1); 287 } 288 289 fname = qemu_opt_get(opts, "rrfile"); 290 if (!fname) { 291 error_report("File name not specified for replay"); 292 exit(1); 293 } 294 295 replay_vmstate_register(); 296 replay_enable(fname, mode); 297 298 out: 299 loc_pop(&loc); 300 } 301 302 void replay_start(void) 303 { 304 if (replay_mode == REPLAY_MODE_NONE) { 305 return; 306 } 307 308 if (replay_blockers) { 309 error_reportf_err(replay_blockers->data, "Record/replay: "); 310 exit(1); 311 } 312 if (!use_icount) { 313 error_report("Please enable icount to use record/replay"); 314 exit(1); 315 } 316 317 /* Timer for snapshotting will be set up here. */ 318 319 replay_enable_events(); 320 } 321 322 void replay_finish(void) 323 { 324 if (replay_mode == REPLAY_MODE_NONE) { 325 return; 326 } 327 328 replay_save_instructions(); 329 330 /* finalize the file */ 331 if (replay_file) { 332 if (replay_mode == REPLAY_MODE_RECORD) { 333 /* write end event */ 334 replay_put_event(EVENT_END); 335 336 /* write header */ 337 fseek(replay_file, 0, SEEK_SET); 338 replay_put_dword(REPLAY_VERSION); 339 } 340 341 fclose(replay_file); 342 replay_file = NULL; 343 } 344 if (replay_filename) { 345 g_free(replay_filename); 346 replay_filename = NULL; 347 } 348 349 replay_finish_events(); 350 replay_mutex_destroy(); 351 } 352 353 void replay_add_blocker(Error *reason) 354 { 355 replay_blockers = g_slist_prepend(replay_blockers, reason); 356 } 357