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-common.h" 13 #include "sysemu/replay.h" 14 #include "replay-internal.h" 15 #include "qemu/timer.h" 16 #include "qemu/main-loop.h" 17 18 ReplayMode replay_mode = REPLAY_MODE_NONE; 19 20 ReplayState replay_state; 21 22 bool replay_next_event_is(int event) 23 { 24 bool res = false; 25 26 /* nothing to skip - not all instructions used */ 27 if (replay_state.instructions_count != 0) { 28 assert(replay_data_kind == EVENT_INSTRUCTION); 29 return event == EVENT_INSTRUCTION; 30 } 31 32 while (true) { 33 if (event == replay_data_kind) { 34 res = true; 35 } 36 switch (replay_data_kind) { 37 default: 38 /* clock, time_t, checkpoint and other events */ 39 return res; 40 } 41 } 42 return res; 43 } 44 45 uint64_t replay_get_current_step(void) 46 { 47 return cpu_get_icount_raw(); 48 } 49 50 int replay_get_instructions(void) 51 { 52 int res = 0; 53 replay_mutex_lock(); 54 if (replay_next_event_is(EVENT_INSTRUCTION)) { 55 res = replay_state.instructions_count; 56 } 57 replay_mutex_unlock(); 58 return res; 59 } 60 61 void replay_account_executed_instructions(void) 62 { 63 if (replay_mode == REPLAY_MODE_PLAY) { 64 replay_mutex_lock(); 65 if (replay_state.instructions_count > 0) { 66 int count = (int)(replay_get_current_step() 67 - replay_state.current_step); 68 replay_state.instructions_count -= count; 69 replay_state.current_step += count; 70 if (replay_state.instructions_count == 0) { 71 assert(replay_data_kind == EVENT_INSTRUCTION); 72 replay_finish_event(); 73 /* Wake up iothread. This is required because 74 timers will not expire until clock counters 75 will be read from the log. */ 76 qemu_notify_event(); 77 } 78 } 79 replay_mutex_unlock(); 80 } 81 } 82 83 bool replay_exception(void) 84 { 85 if (replay_mode == REPLAY_MODE_RECORD) { 86 replay_save_instructions(); 87 replay_mutex_lock(); 88 replay_put_event(EVENT_EXCEPTION); 89 replay_mutex_unlock(); 90 return true; 91 } else if (replay_mode == REPLAY_MODE_PLAY) { 92 bool res = replay_has_exception(); 93 if (res) { 94 replay_mutex_lock(); 95 replay_finish_event(); 96 replay_mutex_unlock(); 97 } 98 return res; 99 } 100 101 return true; 102 } 103 104 bool replay_has_exception(void) 105 { 106 bool res = false; 107 if (replay_mode == REPLAY_MODE_PLAY) { 108 replay_account_executed_instructions(); 109 replay_mutex_lock(); 110 res = replay_next_event_is(EVENT_EXCEPTION); 111 replay_mutex_unlock(); 112 } 113 114 return res; 115 } 116 117 bool replay_interrupt(void) 118 { 119 if (replay_mode == REPLAY_MODE_RECORD) { 120 replay_save_instructions(); 121 replay_mutex_lock(); 122 replay_put_event(EVENT_INTERRUPT); 123 replay_mutex_unlock(); 124 return true; 125 } else if (replay_mode == REPLAY_MODE_PLAY) { 126 bool res = replay_has_interrupt(); 127 if (res) { 128 replay_mutex_lock(); 129 replay_finish_event(); 130 replay_mutex_unlock(); 131 } 132 return res; 133 } 134 135 return true; 136 } 137 138 bool replay_has_interrupt(void) 139 { 140 bool res = false; 141 if (replay_mode == REPLAY_MODE_PLAY) { 142 replay_account_executed_instructions(); 143 replay_mutex_lock(); 144 res = replay_next_event_is(EVENT_INTERRUPT); 145 replay_mutex_unlock(); 146 } 147 return res; 148 } 149