]> git.proxmox.com Git - mirror_qemu.git/blob - replay/replay.c
replay: interrupts and exceptions
[mirror_qemu.git] / replay / replay.c
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 }