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