1 /* 2 * replay-internal.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 "sysemu/replay.h" 14 #include "sysemu/runstate.h" 15 #include "replay-internal.h" 16 #include "qemu/error-report.h" 17 #include "qemu/main-loop.h" 18 19 /* Mutex to protect reading and writing events to the log. 20 data_kind and has_unread_data are also protected 21 by this mutex. 22 It also protects replay events queue which stores events to be 23 written or read to the log. */ 24 static QemuMutex lock; 25 /* Condition and queue for fair ordering of mutex lock requests. */ 26 static QemuCond mutex_cond; 27 static unsigned long mutex_head, mutex_tail; 28 29 /* File for replay writing */ 30 static bool write_error; 31 FILE *replay_file; 32 33 static void replay_write_error(void) 34 { 35 if (!write_error) { 36 error_report("replay write error"); 37 write_error = true; 38 } 39 } 40 41 static void replay_read_error(void) 42 { 43 error_report("error reading the replay data"); 44 exit(1); 45 } 46 47 void replay_put_byte(uint8_t byte) 48 { 49 if (replay_file) { 50 if (putc(byte, replay_file) == EOF) { 51 replay_write_error(); 52 } 53 } 54 } 55 56 void replay_put_event(uint8_t event) 57 { 58 assert(event < EVENT_COUNT); 59 replay_put_byte(event); 60 } 61 62 63 void replay_put_word(uint16_t word) 64 { 65 replay_put_byte(word >> 8); 66 replay_put_byte(word); 67 } 68 69 void replay_put_dword(uint32_t dword) 70 { 71 replay_put_word(dword >> 16); 72 replay_put_word(dword); 73 } 74 75 void replay_put_qword(int64_t qword) 76 { 77 replay_put_dword(qword >> 32); 78 replay_put_dword(qword); 79 } 80 81 void replay_put_array(const uint8_t *buf, size_t size) 82 { 83 if (replay_file) { 84 replay_put_dword(size); 85 if (fwrite(buf, 1, size, replay_file) != size) { 86 replay_write_error(); 87 } 88 } 89 } 90 91 uint8_t replay_get_byte(void) 92 { 93 uint8_t byte = 0; 94 if (replay_file) { 95 int r = getc(replay_file); 96 if (r == EOF) { 97 replay_read_error(); 98 } 99 byte = r; 100 } 101 return byte; 102 } 103 104 uint16_t replay_get_word(void) 105 { 106 uint16_t word = 0; 107 if (replay_file) { 108 word = replay_get_byte(); 109 word = (word << 8) + replay_get_byte(); 110 } 111 112 return word; 113 } 114 115 uint32_t replay_get_dword(void) 116 { 117 uint32_t dword = 0; 118 if (replay_file) { 119 dword = replay_get_word(); 120 dword = (dword << 16) + replay_get_word(); 121 } 122 123 return dword; 124 } 125 126 int64_t replay_get_qword(void) 127 { 128 int64_t qword = 0; 129 if (replay_file) { 130 qword = replay_get_dword(); 131 qword = (qword << 32) + replay_get_dword(); 132 } 133 134 return qword; 135 } 136 137 void replay_get_array(uint8_t *buf, size_t *size) 138 { 139 if (replay_file) { 140 *size = replay_get_dword(); 141 if (fread(buf, 1, *size, replay_file) != *size) { 142 replay_read_error(); 143 } 144 } 145 } 146 147 void replay_get_array_alloc(uint8_t **buf, size_t *size) 148 { 149 if (replay_file) { 150 *size = replay_get_dword(); 151 *buf = g_malloc(*size); 152 if (fread(*buf, 1, *size, replay_file) != *size) { 153 replay_read_error(); 154 } 155 } 156 } 157 158 void replay_check_error(void) 159 { 160 if (replay_file) { 161 if (feof(replay_file)) { 162 error_report("replay file is over"); 163 qemu_system_vmstop_request_prepare(); 164 qemu_system_vmstop_request(RUN_STATE_PAUSED); 165 } else if (ferror(replay_file)) { 166 error_report("replay file is over or something goes wrong"); 167 qemu_system_vmstop_request_prepare(); 168 qemu_system_vmstop_request(RUN_STATE_INTERNAL_ERROR); 169 } 170 } 171 } 172 173 void replay_fetch_data_kind(void) 174 { 175 if (replay_file) { 176 if (!replay_state.has_unread_data) { 177 replay_state.data_kind = replay_get_byte(); 178 replay_state.current_event++; 179 if (replay_state.data_kind == EVENT_INSTRUCTION) { 180 replay_state.instruction_count = replay_get_dword(); 181 } 182 replay_check_error(); 183 replay_state.has_unread_data = true; 184 if (replay_state.data_kind >= EVENT_COUNT) { 185 error_report("Replay: unknown event kind %d", 186 replay_state.data_kind); 187 exit(1); 188 } 189 } 190 } 191 } 192 193 void replay_finish_event(void) 194 { 195 replay_state.has_unread_data = false; 196 replay_fetch_data_kind(); 197 } 198 199 static __thread bool replay_locked; 200 201 void replay_mutex_init(void) 202 { 203 qemu_mutex_init(&lock); 204 qemu_cond_init(&mutex_cond); 205 /* Hold the mutex while we start-up */ 206 replay_locked = true; 207 ++mutex_tail; 208 } 209 210 bool replay_mutex_locked(void) 211 { 212 return replay_locked; 213 } 214 215 /* Ordering constraints, replay_lock must be taken before BQL */ 216 void replay_mutex_lock(void) 217 { 218 if (replay_mode != REPLAY_MODE_NONE) { 219 unsigned long id; 220 g_assert(!bql_locked()); 221 g_assert(!replay_mutex_locked()); 222 qemu_mutex_lock(&lock); 223 id = mutex_tail++; 224 while (id != mutex_head) { 225 qemu_cond_wait(&mutex_cond, &lock); 226 } 227 replay_locked = true; 228 qemu_mutex_unlock(&lock); 229 } 230 } 231 232 void replay_mutex_unlock(void) 233 { 234 if (replay_mode != REPLAY_MODE_NONE) { 235 g_assert(replay_mutex_locked()); 236 qemu_mutex_lock(&lock); 237 ++mutex_head; 238 replay_locked = false; 239 qemu_cond_broadcast(&mutex_cond); 240 qemu_mutex_unlock(&lock); 241 } 242 } 243 244 void replay_advance_current_icount(uint64_t current_icount) 245 { 246 int diff = (int)(current_icount - replay_state.current_icount); 247 248 /* Time can only go forward */ 249 assert(diff >= 0); 250 251 if (replay_mode == REPLAY_MODE_RECORD) { 252 if (diff > 0) { 253 replay_put_event(EVENT_INSTRUCTION); 254 replay_put_dword(diff); 255 replay_state.current_icount += diff; 256 } 257 } else if (replay_mode == REPLAY_MODE_PLAY) { 258 if (diff > 0) { 259 replay_state.instruction_count -= diff; 260 replay_state.current_icount += diff; 261 if (replay_state.instruction_count == 0) { 262 assert(replay_state.data_kind == EVENT_INSTRUCTION); 263 replay_finish_event(); 264 /* Wake up iothread. This is required because 265 timers will not expire until clock counters 266 will be read from the log. */ 267 qemu_notify_event(); 268 } 269 } 270 /* Execution reached the break step */ 271 if (replay_break_icount == replay_state.current_icount) { 272 /* Cannot make callback directly from the vCPU thread */ 273 timer_mod_ns(replay_break_timer, 274 qemu_clock_get_ns(QEMU_CLOCK_REALTIME)); 275 } 276 } 277 } 278 279 /*! Saves cached instructions. */ 280 void replay_save_instructions(void) 281 { 282 if (replay_file && replay_mode == REPLAY_MODE_RECORD) { 283 g_assert(replay_mutex_locked()); 284 replay_advance_current_icount(replay_get_current_icount()); 285 } 286 } 287