overall/alpha tcg cpus|hppa: Fix Lesser GPL version number
[qemu.git] / softmmu / cpu-timers.c
1 /*
2 * QEMU System Emulator
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25 #include "qemu/osdep.h"
26 #include "qemu-common.h"
27 #include "qemu/cutils.h"
28 #include "migration/vmstate.h"
29 #include "qapi/error.h"
30 #include "qemu/error-report.h"
31 #include "exec/exec-all.h"
32 #include "sysemu/cpus.h"
33 #include "sysemu/qtest.h"
34 #include "qemu/main-loop.h"
35 #include "qemu/option.h"
36 #include "qemu/seqlock.h"
37 #include "sysemu/replay.h"
38 #include "sysemu/runstate.h"
39 #include "hw/core/cpu.h"
40 #include "sysemu/cpu-timers.h"
41 #include "sysemu/cpu-throttle.h"
42 #include "timers-state.h"
43
44 /* clock and ticks */
45
46 static int64_t cpu_get_ticks_locked(void)
47 {
48 int64_t ticks = timers_state.cpu_ticks_offset;
49 if (timers_state.cpu_ticks_enabled) {
50 ticks += cpu_get_host_ticks();
51 }
52
53 if (timers_state.cpu_ticks_prev > ticks) {
54 /* Non increasing ticks may happen if the host uses software suspend. */
55 timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
56 ticks = timers_state.cpu_ticks_prev;
57 }
58
59 timers_state.cpu_ticks_prev = ticks;
60 return ticks;
61 }
62
63 /*
64 * return the time elapsed in VM between vm_start and vm_stop.
65 * cpu_get_ticks() uses units of the host CPU cycle counter.
66 */
67 int64_t cpu_get_ticks(void)
68 {
69 int64_t ticks;
70
71 qemu_spin_lock(&timers_state.vm_clock_lock);
72 ticks = cpu_get_ticks_locked();
73 qemu_spin_unlock(&timers_state.vm_clock_lock);
74 return ticks;
75 }
76
77 int64_t cpu_get_clock_locked(void)
78 {
79 int64_t time;
80
81 time = timers_state.cpu_clock_offset;
82 if (timers_state.cpu_ticks_enabled) {
83 time += get_clock();
84 }
85
86 return time;
87 }
88
89 /*
90 * Return the monotonic time elapsed in VM, i.e.,
91 * the time between vm_start and vm_stop
92 */
93 int64_t cpu_get_clock(void)
94 {
95 int64_t ti;
96 unsigned start;
97
98 do {
99 start = seqlock_read_begin(&timers_state.vm_clock_seqlock);
100 ti = cpu_get_clock_locked();
101 } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start));
102
103 return ti;
104 }
105
106 /*
107 * enable cpu_get_ticks()
108 * Caller must hold BQL which serves as mutex for vm_clock_seqlock.
109 */
110 void cpu_enable_ticks(void)
111 {
112 seqlock_write_lock(&timers_state.vm_clock_seqlock,
113 &timers_state.vm_clock_lock);
114 if (!timers_state.cpu_ticks_enabled) {
115 timers_state.cpu_ticks_offset -= cpu_get_host_ticks();
116 timers_state.cpu_clock_offset -= get_clock();
117 timers_state.cpu_ticks_enabled = 1;
118 }
119 seqlock_write_unlock(&timers_state.vm_clock_seqlock,
120 &timers_state.vm_clock_lock);
121 }
122
123 /*
124 * disable cpu_get_ticks() : the clock is stopped. You must not call
125 * cpu_get_ticks() after that.
126 * Caller must hold BQL which serves as mutex for vm_clock_seqlock.
127 */
128 void cpu_disable_ticks(void)
129 {
130 seqlock_write_lock(&timers_state.vm_clock_seqlock,
131 &timers_state.vm_clock_lock);
132 if (timers_state.cpu_ticks_enabled) {
133 timers_state.cpu_ticks_offset += cpu_get_host_ticks();
134 timers_state.cpu_clock_offset = cpu_get_clock_locked();
135 timers_state.cpu_ticks_enabled = 0;
136 }
137 seqlock_write_unlock(&timers_state.vm_clock_seqlock,
138 &timers_state.vm_clock_lock);
139 }
140
141 static bool icount_state_needed(void *opaque)
142 {
143 return icount_enabled();
144 }
145
146 static bool warp_timer_state_needed(void *opaque)
147 {
148 TimersState *s = opaque;
149 return s->icount_warp_timer != NULL;
150 }
151
152 static bool adjust_timers_state_needed(void *opaque)
153 {
154 TimersState *s = opaque;
155 return s->icount_rt_timer != NULL;
156 }
157
158 static bool icount_shift_state_needed(void *opaque)
159 {
160 return icount_enabled() == 2;
161 }
162
163 /*
164 * Subsection for warp timer migration is optional, because may not be created
165 */
166 static const VMStateDescription icount_vmstate_warp_timer = {
167 .name = "timer/icount/warp_timer",
168 .version_id = 1,
169 .minimum_version_id = 1,
170 .needed = warp_timer_state_needed,
171 .fields = (VMStateField[]) {
172 VMSTATE_INT64(vm_clock_warp_start, TimersState),
173 VMSTATE_TIMER_PTR(icount_warp_timer, TimersState),
174 VMSTATE_END_OF_LIST()
175 }
176 };
177
178 static const VMStateDescription icount_vmstate_adjust_timers = {
179 .name = "timer/icount/timers",
180 .version_id = 1,
181 .minimum_version_id = 1,
182 .needed = adjust_timers_state_needed,
183 .fields = (VMStateField[]) {
184 VMSTATE_TIMER_PTR(icount_rt_timer, TimersState),
185 VMSTATE_TIMER_PTR(icount_vm_timer, TimersState),
186 VMSTATE_END_OF_LIST()
187 }
188 };
189
190 static const VMStateDescription icount_vmstate_shift = {
191 .name = "timer/icount/shift",
192 .version_id = 1,
193 .minimum_version_id = 1,
194 .needed = icount_shift_state_needed,
195 .fields = (VMStateField[]) {
196 VMSTATE_INT16(icount_time_shift, TimersState),
197 VMSTATE_END_OF_LIST()
198 }
199 };
200
201 /*
202 * This is a subsection for icount migration.
203 */
204 static const VMStateDescription icount_vmstate_timers = {
205 .name = "timer/icount",
206 .version_id = 1,
207 .minimum_version_id = 1,
208 .needed = icount_state_needed,
209 .fields = (VMStateField[]) {
210 VMSTATE_INT64(qemu_icount_bias, TimersState),
211 VMSTATE_INT64(qemu_icount, TimersState),
212 VMSTATE_END_OF_LIST()
213 },
214 .subsections = (const VMStateDescription * []) {
215 &icount_vmstate_warp_timer,
216 &icount_vmstate_adjust_timers,
217 &icount_vmstate_shift,
218 NULL
219 }
220 };
221
222 static const VMStateDescription vmstate_timers = {
223 .name = "timer",
224 .version_id = 2,
225 .minimum_version_id = 1,
226 .fields = (VMStateField[]) {
227 VMSTATE_INT64(cpu_ticks_offset, TimersState),
228 VMSTATE_UNUSED(8),
229 VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
230 VMSTATE_END_OF_LIST()
231 },
232 .subsections = (const VMStateDescription * []) {
233 &icount_vmstate_timers,
234 NULL
235 }
236 };
237
238 static void do_nothing(CPUState *cpu, run_on_cpu_data unused)
239 {
240 }
241
242 void qemu_timer_notify_cb(void *opaque, QEMUClockType type)
243 {
244 if (!icount_enabled() || type != QEMU_CLOCK_VIRTUAL) {
245 qemu_notify_event();
246 return;
247 }
248
249 if (qemu_in_vcpu_thread()) {
250 /*
251 * A CPU is currently running; kick it back out to the
252 * tcg_cpu_exec() loop so it will recalculate its
253 * icount deadline immediately.
254 */
255 qemu_cpu_kick(current_cpu);
256 } else if (first_cpu) {
257 /*
258 * qemu_cpu_kick is not enough to kick a halted CPU out of
259 * qemu_tcg_wait_io_event. async_run_on_cpu, instead,
260 * causes cpu_thread_is_idle to return false. This way,
261 * handle_icount_deadline can run.
262 * If we have no CPUs at all for some reason, we don't
263 * need to do anything.
264 */
265 async_run_on_cpu(first_cpu, do_nothing, RUN_ON_CPU_NULL);
266 }
267 }
268
269 TimersState timers_state;
270
271 /* initialize timers state and the cpu throttle for convenience */
272 void cpu_timers_init(void)
273 {
274 seqlock_init(&timers_state.vm_clock_seqlock);
275 qemu_spin_init(&timers_state.vm_clock_lock);
276 vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
277
278 cpu_throttle_init();
279 }