]> git.proxmox.com Git - mirror_qemu.git/blame - system/cpu-timers.c
target/arm: Expose arm_cpu_mp_affinity() in 'multiprocessing.h' header
[mirror_qemu.git] / system / cpu-timers.c
CommitLineData
740b1759
CF
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"
740b1759
CF
26#include "qemu/cutils.h"
27#include "migration/vmstate.h"
28#include "qapi/error.h"
29#include "qemu/error-report.h"
740b1759 30#include "sysemu/cpus.h"
740b1759
CF
31#include "qemu/main-loop.h"
32#include "qemu/option.h"
33#include "qemu/seqlock.h"
34#include "sysemu/replay.h"
35#include "sysemu/runstate.h"
36#include "hw/core/cpu.h"
37#include "sysemu/cpu-timers.h"
38#include "sysemu/cpu-throttle.h"
8d7f2e76 39#include "sysemu/cpu-timers-internal.h"
740b1759
CF
40
41/* clock and ticks */
42
43static int64_t cpu_get_ticks_locked(void)
44{
45 int64_t ticks = timers_state.cpu_ticks_offset;
46 if (timers_state.cpu_ticks_enabled) {
47 ticks += cpu_get_host_ticks();
48 }
49
50 if (timers_state.cpu_ticks_prev > ticks) {
51 /* Non increasing ticks may happen if the host uses software suspend. */
52 timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
53 ticks = timers_state.cpu_ticks_prev;
54 }
55
56 timers_state.cpu_ticks_prev = ticks;
57 return ticks;
58}
59
60/*
430065da
CF
61 * return the time elapsed in VM between vm_start and vm_stop.
62 * cpu_get_ticks() uses units of the host CPU cycle counter.
740b1759
CF
63 */
64int64_t cpu_get_ticks(void)
65{
66 int64_t ticks;
67
740b1759
CF
68 qemu_spin_lock(&timers_state.vm_clock_lock);
69 ticks = cpu_get_ticks_locked();
70 qemu_spin_unlock(&timers_state.vm_clock_lock);
71 return ticks;
72}
73
74int64_t cpu_get_clock_locked(void)
75{
76 int64_t time;
77
78 time = timers_state.cpu_clock_offset;
79 if (timers_state.cpu_ticks_enabled) {
80 time += get_clock();
81 }
82
83 return time;
84}
85
86/*
87 * Return the monotonic time elapsed in VM, i.e.,
88 * the time between vm_start and vm_stop
89 */
90int64_t cpu_get_clock(void)
91{
92 int64_t ti;
93 unsigned start;
94
95 do {
96 start = seqlock_read_begin(&timers_state.vm_clock_seqlock);
97 ti = cpu_get_clock_locked();
98 } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start));
99
100 return ti;
101}
102
103/*
104 * enable cpu_get_ticks()
105 * Caller must hold BQL which serves as mutex for vm_clock_seqlock.
106 */
107void cpu_enable_ticks(void)
108{
109 seqlock_write_lock(&timers_state.vm_clock_seqlock,
110 &timers_state.vm_clock_lock);
111 if (!timers_state.cpu_ticks_enabled) {
112 timers_state.cpu_ticks_offset -= cpu_get_host_ticks();
113 timers_state.cpu_clock_offset -= get_clock();
114 timers_state.cpu_ticks_enabled = 1;
115 }
116 seqlock_write_unlock(&timers_state.vm_clock_seqlock,
117 &timers_state.vm_clock_lock);
118}
119
120/*
121 * disable cpu_get_ticks() : the clock is stopped. You must not call
122 * cpu_get_ticks() after that.
123 * Caller must hold BQL which serves as mutex for vm_clock_seqlock.
124 */
125void cpu_disable_ticks(void)
126{
127 seqlock_write_lock(&timers_state.vm_clock_seqlock,
128 &timers_state.vm_clock_lock);
129 if (timers_state.cpu_ticks_enabled) {
130 timers_state.cpu_ticks_offset += cpu_get_host_ticks();
131 timers_state.cpu_clock_offset = cpu_get_clock_locked();
132 timers_state.cpu_ticks_enabled = 0;
133 }
134 seqlock_write_unlock(&timers_state.vm_clock_seqlock,
135 &timers_state.vm_clock_lock);
136}
137
138static bool icount_state_needed(void *opaque)
139{
140 return icount_enabled();
141}
142
143static bool warp_timer_state_needed(void *opaque)
144{
145 TimersState *s = opaque;
146 return s->icount_warp_timer != NULL;
147}
148
149static bool adjust_timers_state_needed(void *opaque)
150{
151 TimersState *s = opaque;
152 return s->icount_rt_timer != NULL;
153}
154
8191d368 155static bool icount_shift_state_needed(void *opaque)
740b1759 156{
8e98c27d 157 return icount_enabled() == ICOUNT_ADAPTATIVE;
740b1759
CF
158}
159
160/*
161 * Subsection for warp timer migration is optional, because may not be created
162 */
163static const VMStateDescription icount_vmstate_warp_timer = {
164 .name = "timer/icount/warp_timer",
165 .version_id = 1,
166 .minimum_version_id = 1,
167 .needed = warp_timer_state_needed,
72ecb4a9 168 .fields = (const VMStateField[]) {
740b1759
CF
169 VMSTATE_INT64(vm_clock_warp_start, TimersState),
170 VMSTATE_TIMER_PTR(icount_warp_timer, TimersState),
171 VMSTATE_END_OF_LIST()
172 }
173};
174
175static const VMStateDescription icount_vmstate_adjust_timers = {
176 .name = "timer/icount/timers",
177 .version_id = 1,
178 .minimum_version_id = 1,
179 .needed = adjust_timers_state_needed,
72ecb4a9 180 .fields = (const VMStateField[]) {
740b1759
CF
181 VMSTATE_TIMER_PTR(icount_rt_timer, TimersState),
182 VMSTATE_TIMER_PTR(icount_vm_timer, TimersState),
183 VMSTATE_END_OF_LIST()
184 }
185};
186
187static const VMStateDescription icount_vmstate_shift = {
188 .name = "timer/icount/shift",
fe852ac2
PD
189 .version_id = 2,
190 .minimum_version_id = 2,
8191d368 191 .needed = icount_shift_state_needed,
72ecb4a9 192 .fields = (const VMStateField[]) {
740b1759 193 VMSTATE_INT16(icount_time_shift, TimersState),
fe852ac2 194 VMSTATE_INT64(last_delta, TimersState),
740b1759
CF
195 VMSTATE_END_OF_LIST()
196 }
197};
198
199/*
200 * This is a subsection for icount migration.
201 */
202static const VMStateDescription icount_vmstate_timers = {
203 .name = "timer/icount",
204 .version_id = 1,
205 .minimum_version_id = 1,
206 .needed = icount_state_needed,
72ecb4a9 207 .fields = (const VMStateField[]) {
740b1759
CF
208 VMSTATE_INT64(qemu_icount_bias, TimersState),
209 VMSTATE_INT64(qemu_icount, TimersState),
210 VMSTATE_END_OF_LIST()
211 },
72ecb4a9 212 .subsections = (const VMStateDescription * const []) {
740b1759
CF
213 &icount_vmstate_warp_timer,
214 &icount_vmstate_adjust_timers,
215 &icount_vmstate_shift,
216 NULL
217 }
218};
219
220static const VMStateDescription vmstate_timers = {
221 .name = "timer",
222 .version_id = 2,
223 .minimum_version_id = 1,
72ecb4a9 224 .fields = (const VMStateField[]) {
740b1759
CF
225 VMSTATE_INT64(cpu_ticks_offset, TimersState),
226 VMSTATE_UNUSED(8),
227 VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
228 VMSTATE_END_OF_LIST()
229 },
72ecb4a9 230 .subsections = (const VMStateDescription * const []) {
740b1759
CF
231 &icount_vmstate_timers,
232 NULL
233 }
234};
235
236static void do_nothing(CPUState *cpu, run_on_cpu_data unused)
237{
238}
239
240void qemu_timer_notify_cb(void *opaque, QEMUClockType type)
241{
242 if (!icount_enabled() || type != QEMU_CLOCK_VIRTUAL) {
243 qemu_notify_event();
244 return;
245 }
246
247 if (qemu_in_vcpu_thread()) {
248 /*
249 * A CPU is currently running; kick it back out to the
250 * tcg_cpu_exec() loop so it will recalculate its
251 * icount deadline immediately.
252 */
253 qemu_cpu_kick(current_cpu);
254 } else if (first_cpu) {
255 /*
256 * qemu_cpu_kick is not enough to kick a halted CPU out of
257 * qemu_tcg_wait_io_event. async_run_on_cpu, instead,
258 * causes cpu_thread_is_idle to return false. This way,
259 * handle_icount_deadline can run.
260 * If we have no CPUs at all for some reason, we don't
261 * need to do anything.
262 */
263 async_run_on_cpu(first_cpu, do_nothing, RUN_ON_CPU_NULL);
264 }
265}
266
267TimersState timers_state;
268
269/* initialize timers state and the cpu throttle for convenience */
270void cpu_timers_init(void)
271{
272 seqlock_init(&timers_state.vm_clock_seqlock);
273 qemu_spin_init(&timers_state.vm_clock_lock);
274 vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
275
276 cpu_throttle_init();
277}