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