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 0xe02006 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 replay_mutex_lock(); 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 replay_mutex_unlock(); 104 } 105 } 106 107 bool replay_exception(void) 108 { 109 if (replay_mode == REPLAY_MODE_RECORD) { 110 replay_save_instructions(); 111 replay_mutex_lock(); 112 replay_put_event(EVENT_EXCEPTION); 113 replay_mutex_unlock(); 114 return true; 115 } else if (replay_mode == REPLAY_MODE_PLAY) { 116 bool res = replay_has_exception(); 117 if (res) { 118 replay_mutex_lock(); 119 replay_finish_event(); 120 replay_mutex_unlock(); 121 } 122 return res; 123 } 124 125 return true; 126 } 127 128 bool replay_has_exception(void) 129 { 130 bool res = false; 131 if (replay_mode == REPLAY_MODE_PLAY) { 132 replay_account_executed_instructions(); 133 replay_mutex_lock(); 134 res = replay_next_event_is(EVENT_EXCEPTION); 135 replay_mutex_unlock(); 136 } 137 138 return res; 139 } 140 141 bool replay_interrupt(void) 142 { 143 if (replay_mode == REPLAY_MODE_RECORD) { 144 replay_save_instructions(); 145 replay_mutex_lock(); 146 replay_put_event(EVENT_INTERRUPT); 147 replay_mutex_unlock(); 148 return true; 149 } else if (replay_mode == REPLAY_MODE_PLAY) { 150 bool res = replay_has_interrupt(); 151 if (res) { 152 replay_mutex_lock(); 153 replay_finish_event(); 154 replay_mutex_unlock(); 155 } 156 return res; 157 } 158 159 return true; 160 } 161 162 bool replay_has_interrupt(void) 163 { 164 bool res = false; 165 if (replay_mode == REPLAY_MODE_PLAY) { 166 replay_account_executed_instructions(); 167 replay_mutex_lock(); 168 res = replay_next_event_is(EVENT_INTERRUPT); 169 replay_mutex_unlock(); 170 } 171 return res; 172 } 173 174 void replay_shutdown_request(ShutdownCause cause) 175 { 176 if (replay_mode == REPLAY_MODE_RECORD) { 177 replay_mutex_lock(); 178 replay_put_event(EVENT_SHUTDOWN + cause); 179 replay_mutex_unlock(); 180 } 181 } 182 183 bool replay_checkpoint(ReplayCheckpoint checkpoint) 184 { 185 bool res = false; 186 assert(EVENT_CHECKPOINT + checkpoint <= EVENT_CHECKPOINT_LAST); 187 replay_save_instructions(); 188 189 if (!replay_file) { 190 return true; 191 } 192 193 replay_mutex_lock(); 194 195 if (replay_mode == REPLAY_MODE_PLAY) { 196 if (replay_next_event_is(EVENT_CHECKPOINT + checkpoint)) { 197 replay_finish_event(); 198 } else if (replay_state.data_kind != EVENT_ASYNC) { 199 res = false; 200 goto out; 201 } 202 replay_read_events(checkpoint); 203 /* replay_read_events may leave some unread events. 204 Return false if not all of the events associated with 205 checkpoint were processed */ 206 res = replay_state.data_kind != EVENT_ASYNC; 207 } else if (replay_mode == REPLAY_MODE_RECORD) { 208 replay_put_event(EVENT_CHECKPOINT + checkpoint); 209 replay_save_events(checkpoint); 210 res = true; 211 } 212 out: 213 replay_mutex_unlock(); 214 return res; 215 } 216 217 static void replay_enable(const char *fname, int mode) 218 { 219 const char *fmode = NULL; 220 assert(!replay_file); 221 222 switch (mode) { 223 case REPLAY_MODE_RECORD: 224 fmode = "wb"; 225 break; 226 case REPLAY_MODE_PLAY: 227 fmode = "rb"; 228 break; 229 default: 230 fprintf(stderr, "Replay: internal error: invalid replay mode\n"); 231 exit(1); 232 } 233 234 atexit(replay_finish); 235 236 replay_mutex_init(); 237 238 replay_file = fopen(fname, fmode); 239 if (replay_file == NULL) { 240 fprintf(stderr, "Replay: open %s: %s\n", fname, strerror(errno)); 241 exit(1); 242 } 243 244 replay_filename = g_strdup(fname); 245 246 replay_mode = mode; 247 replay_state.data_kind = -1; 248 replay_state.instructions_count = 0; 249 replay_state.current_step = 0; 250 replay_state.has_unread_data = 0; 251 252 /* skip file header for RECORD and check it for PLAY */ 253 if (replay_mode == REPLAY_MODE_RECORD) { 254 fseek(replay_file, HEADER_SIZE, SEEK_SET); 255 } else if (replay_mode == REPLAY_MODE_PLAY) { 256 unsigned int version = replay_get_dword(); 257 if (version != REPLAY_VERSION) { 258 fprintf(stderr, "Replay: invalid input log file version\n"); 259 exit(1); 260 } 261 /* go to the beginning */ 262 fseek(replay_file, HEADER_SIZE, SEEK_SET); 263 replay_fetch_data_kind(); 264 } 265 266 replay_init_events(); 267 } 268 269 void replay_configure(QemuOpts *opts) 270 { 271 const char *fname; 272 const char *rr; 273 ReplayMode mode = REPLAY_MODE_NONE; 274 Location loc; 275 276 if (!opts) { 277 return; 278 } 279 280 loc_push_none(&loc); 281 qemu_opts_loc_restore(opts); 282 283 rr = qemu_opt_get(opts, "rr"); 284 if (!rr) { 285 /* Just enabling icount */ 286 goto out; 287 } else if (!strcmp(rr, "record")) { 288 mode = REPLAY_MODE_RECORD; 289 } else if (!strcmp(rr, "replay")) { 290 mode = REPLAY_MODE_PLAY; 291 } else { 292 error_report("Invalid icount rr option: %s", rr); 293 exit(1); 294 } 295 296 fname = qemu_opt_get(opts, "rrfile"); 297 if (!fname) { 298 error_report("File name not specified for replay"); 299 exit(1); 300 } 301 302 replay_snapshot = g_strdup(qemu_opt_get(opts, "rrsnapshot")); 303 replay_vmstate_register(); 304 replay_enable(fname, mode); 305 306 out: 307 loc_pop(&loc); 308 } 309 310 void replay_start(void) 311 { 312 if (replay_mode == REPLAY_MODE_NONE) { 313 return; 314 } 315 316 if (replay_blockers) { 317 error_reportf_err(replay_blockers->data, "Record/replay: "); 318 exit(1); 319 } 320 if (!use_icount) { 321 error_report("Please enable icount to use record/replay"); 322 exit(1); 323 } 324 325 /* Timer for snapshotting will be set up here. */ 326 327 replay_enable_events(); 328 } 329 330 void replay_finish(void) 331 { 332 if (replay_mode == REPLAY_MODE_NONE) { 333 return; 334 } 335 336 replay_save_instructions(); 337 338 /* finalize the file */ 339 if (replay_file) { 340 if (replay_mode == REPLAY_MODE_RECORD) { 341 /* write end event */ 342 replay_put_event(EVENT_END); 343 344 /* write header */ 345 fseek(replay_file, 0, SEEK_SET); 346 replay_put_dword(REPLAY_VERSION); 347 } 348 349 fclose(replay_file); 350 replay_file = NULL; 351 } 352 if (replay_filename) { 353 g_free(replay_filename); 354 replay_filename = NULL; 355 } 356 357 g_free(replay_snapshot); 358 replay_snapshot = NULL; 359 360 replay_finish_events(); 361 replay_mutex_destroy(); 362 } 363 364 void replay_add_blocker(Error *reason) 365 { 366 replay_blockers = g_slist_prepend(replay_blockers, reason); 367 } 368