18d7f2e76SPhilippe Mathieu-Daudé /*
28d7f2e76SPhilippe Mathieu-Daudé * QEMU System Emulator
38d7f2e76SPhilippe Mathieu-Daudé *
48d7f2e76SPhilippe Mathieu-Daudé * Copyright (c) 2003-2008 Fabrice Bellard
58d7f2e76SPhilippe Mathieu-Daudé *
68d7f2e76SPhilippe Mathieu-Daudé * Permission is hereby granted, free of charge, to any person obtaining a copy
78d7f2e76SPhilippe Mathieu-Daudé * of this software and associated documentation files (the "Software"), to deal
88d7f2e76SPhilippe Mathieu-Daudé * in the Software without restriction, including without limitation the rights
98d7f2e76SPhilippe Mathieu-Daudé * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
108d7f2e76SPhilippe Mathieu-Daudé * copies of the Software, and to permit persons to whom the Software is
118d7f2e76SPhilippe Mathieu-Daudé * furnished to do so, subject to the following conditions:
128d7f2e76SPhilippe Mathieu-Daudé *
138d7f2e76SPhilippe Mathieu-Daudé * The above copyright notice and this permission notice shall be included in
148d7f2e76SPhilippe Mathieu-Daudé * all copies or substantial portions of the Software.
158d7f2e76SPhilippe Mathieu-Daudé *
168d7f2e76SPhilippe Mathieu-Daudé * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178d7f2e76SPhilippe Mathieu-Daudé * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188d7f2e76SPhilippe Mathieu-Daudé * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
198d7f2e76SPhilippe Mathieu-Daudé * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
208d7f2e76SPhilippe Mathieu-Daudé * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
218d7f2e76SPhilippe Mathieu-Daudé * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
228d7f2e76SPhilippe Mathieu-Daudé * THE SOFTWARE.
238d7f2e76SPhilippe Mathieu-Daudé */
248d7f2e76SPhilippe Mathieu-Daudé
258d7f2e76SPhilippe Mathieu-Daudé #include "qemu/osdep.h"
268d7f2e76SPhilippe Mathieu-Daudé #include "qemu/cutils.h"
278d7f2e76SPhilippe Mathieu-Daudé #include "migration/vmstate.h"
288d7f2e76SPhilippe Mathieu-Daudé #include "qapi/error.h"
298d7f2e76SPhilippe Mathieu-Daudé #include "qemu/error-report.h"
308d7f2e76SPhilippe Mathieu-Daudé #include "sysemu/cpus.h"
318d7f2e76SPhilippe Mathieu-Daudé #include "qemu/main-loop.h"
328d7f2e76SPhilippe Mathieu-Daudé #include "qemu/option.h"
338d7f2e76SPhilippe Mathieu-Daudé #include "qemu/seqlock.h"
348d7f2e76SPhilippe Mathieu-Daudé #include "sysemu/replay.h"
358d7f2e76SPhilippe Mathieu-Daudé #include "sysemu/runstate.h"
368d7f2e76SPhilippe Mathieu-Daudé #include "hw/core/cpu.h"
378d7f2e76SPhilippe Mathieu-Daudé #include "sysemu/cpu-timers.h"
388d7f2e76SPhilippe Mathieu-Daudé #include "sysemu/cpu-timers-internal.h"
398d7f2e76SPhilippe Mathieu-Daudé
408d7f2e76SPhilippe Mathieu-Daudé /* clock and ticks */
418d7f2e76SPhilippe Mathieu-Daudé
cpu_get_ticks_locked(void)428d7f2e76SPhilippe Mathieu-Daudé static int64_t cpu_get_ticks_locked(void)
438d7f2e76SPhilippe Mathieu-Daudé {
448d7f2e76SPhilippe Mathieu-Daudé int64_t ticks = timers_state.cpu_ticks_offset;
458d7f2e76SPhilippe Mathieu-Daudé if (timers_state.cpu_ticks_enabled) {
468d7f2e76SPhilippe Mathieu-Daudé ticks += cpu_get_host_ticks();
478d7f2e76SPhilippe Mathieu-Daudé }
488d7f2e76SPhilippe Mathieu-Daudé
498d7f2e76SPhilippe Mathieu-Daudé if (timers_state.cpu_ticks_prev > ticks) {
508d7f2e76SPhilippe Mathieu-Daudé /* Non increasing ticks may happen if the host uses software suspend. */
518d7f2e76SPhilippe Mathieu-Daudé timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks;
528d7f2e76SPhilippe Mathieu-Daudé ticks = timers_state.cpu_ticks_prev;
538d7f2e76SPhilippe Mathieu-Daudé }
548d7f2e76SPhilippe Mathieu-Daudé
558d7f2e76SPhilippe Mathieu-Daudé timers_state.cpu_ticks_prev = ticks;
568d7f2e76SPhilippe Mathieu-Daudé return ticks;
578d7f2e76SPhilippe Mathieu-Daudé }
588d7f2e76SPhilippe Mathieu-Daudé
598d7f2e76SPhilippe Mathieu-Daudé /*
608d7f2e76SPhilippe Mathieu-Daudé * return the time elapsed in VM between vm_start and vm_stop.
618d7f2e76SPhilippe Mathieu-Daudé * cpu_get_ticks() uses units of the host CPU cycle counter.
628d7f2e76SPhilippe Mathieu-Daudé */
cpu_get_ticks(void)638d7f2e76SPhilippe Mathieu-Daudé int64_t cpu_get_ticks(void)
648d7f2e76SPhilippe Mathieu-Daudé {
658d7f2e76SPhilippe Mathieu-Daudé int64_t ticks;
668d7f2e76SPhilippe Mathieu-Daudé
678d7f2e76SPhilippe Mathieu-Daudé qemu_spin_lock(&timers_state.vm_clock_lock);
688d7f2e76SPhilippe Mathieu-Daudé ticks = cpu_get_ticks_locked();
698d7f2e76SPhilippe Mathieu-Daudé qemu_spin_unlock(&timers_state.vm_clock_lock);
708d7f2e76SPhilippe Mathieu-Daudé return ticks;
718d7f2e76SPhilippe Mathieu-Daudé }
728d7f2e76SPhilippe Mathieu-Daudé
cpu_get_clock_locked(void)738d7f2e76SPhilippe Mathieu-Daudé int64_t cpu_get_clock_locked(void)
748d7f2e76SPhilippe Mathieu-Daudé {
758d7f2e76SPhilippe Mathieu-Daudé int64_t time;
768d7f2e76SPhilippe Mathieu-Daudé
778d7f2e76SPhilippe Mathieu-Daudé time = timers_state.cpu_clock_offset;
788d7f2e76SPhilippe Mathieu-Daudé if (timers_state.cpu_ticks_enabled) {
798d7f2e76SPhilippe Mathieu-Daudé time += get_clock();
808d7f2e76SPhilippe Mathieu-Daudé }
818d7f2e76SPhilippe Mathieu-Daudé
828d7f2e76SPhilippe Mathieu-Daudé return time;
838d7f2e76SPhilippe Mathieu-Daudé }
848d7f2e76SPhilippe Mathieu-Daudé
858d7f2e76SPhilippe Mathieu-Daudé /*
868d7f2e76SPhilippe Mathieu-Daudé * Return the monotonic time elapsed in VM, i.e.,
878d7f2e76SPhilippe Mathieu-Daudé * the time between vm_start and vm_stop
888d7f2e76SPhilippe Mathieu-Daudé */
cpu_get_clock(void)898d7f2e76SPhilippe Mathieu-Daudé int64_t cpu_get_clock(void)
908d7f2e76SPhilippe Mathieu-Daudé {
918d7f2e76SPhilippe Mathieu-Daudé int64_t ti;
928d7f2e76SPhilippe Mathieu-Daudé unsigned start;
938d7f2e76SPhilippe Mathieu-Daudé
948d7f2e76SPhilippe Mathieu-Daudé do {
958d7f2e76SPhilippe Mathieu-Daudé start = seqlock_read_begin(&timers_state.vm_clock_seqlock);
968d7f2e76SPhilippe Mathieu-Daudé ti = cpu_get_clock_locked();
978d7f2e76SPhilippe Mathieu-Daudé } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start));
988d7f2e76SPhilippe Mathieu-Daudé
998d7f2e76SPhilippe Mathieu-Daudé return ti;
1008d7f2e76SPhilippe Mathieu-Daudé }
1018d7f2e76SPhilippe Mathieu-Daudé
1028d7f2e76SPhilippe Mathieu-Daudé /*
1038d7f2e76SPhilippe Mathieu-Daudé * enable cpu_get_ticks()
1048d7f2e76SPhilippe Mathieu-Daudé * Caller must hold BQL which serves as mutex for vm_clock_seqlock.
1058d7f2e76SPhilippe Mathieu-Daudé */
cpu_enable_ticks(void)1068d7f2e76SPhilippe Mathieu-Daudé void cpu_enable_ticks(void)
1078d7f2e76SPhilippe Mathieu-Daudé {
1088d7f2e76SPhilippe Mathieu-Daudé seqlock_write_lock(&timers_state.vm_clock_seqlock,
1098d7f2e76SPhilippe Mathieu-Daudé &timers_state.vm_clock_lock);
1108d7f2e76SPhilippe Mathieu-Daudé if (!timers_state.cpu_ticks_enabled) {
1118d7f2e76SPhilippe Mathieu-Daudé timers_state.cpu_ticks_offset -= cpu_get_host_ticks();
1128d7f2e76SPhilippe Mathieu-Daudé timers_state.cpu_clock_offset -= get_clock();
1138d7f2e76SPhilippe Mathieu-Daudé timers_state.cpu_ticks_enabled = 1;
1148d7f2e76SPhilippe Mathieu-Daudé }
1158d7f2e76SPhilippe Mathieu-Daudé seqlock_write_unlock(&timers_state.vm_clock_seqlock,
1168d7f2e76SPhilippe Mathieu-Daudé &timers_state.vm_clock_lock);
1178d7f2e76SPhilippe Mathieu-Daudé }
1188d7f2e76SPhilippe Mathieu-Daudé
1198d7f2e76SPhilippe Mathieu-Daudé /*
1208d7f2e76SPhilippe Mathieu-Daudé * disable cpu_get_ticks() : the clock is stopped. You must not call
1218d7f2e76SPhilippe Mathieu-Daudé * cpu_get_ticks() after that.
1228d7f2e76SPhilippe Mathieu-Daudé * Caller must hold BQL which serves as mutex for vm_clock_seqlock.
1238d7f2e76SPhilippe Mathieu-Daudé */
cpu_disable_ticks(void)1248d7f2e76SPhilippe Mathieu-Daudé void cpu_disable_ticks(void)
1258d7f2e76SPhilippe Mathieu-Daudé {
1268d7f2e76SPhilippe Mathieu-Daudé seqlock_write_lock(&timers_state.vm_clock_seqlock,
1278d7f2e76SPhilippe Mathieu-Daudé &timers_state.vm_clock_lock);
1288d7f2e76SPhilippe Mathieu-Daudé if (timers_state.cpu_ticks_enabled) {
1298d7f2e76SPhilippe Mathieu-Daudé timers_state.cpu_ticks_offset += cpu_get_host_ticks();
1308d7f2e76SPhilippe Mathieu-Daudé timers_state.cpu_clock_offset = cpu_get_clock_locked();
1318d7f2e76SPhilippe Mathieu-Daudé timers_state.cpu_ticks_enabled = 0;
1328d7f2e76SPhilippe Mathieu-Daudé }
1338d7f2e76SPhilippe Mathieu-Daudé seqlock_write_unlock(&timers_state.vm_clock_seqlock,
1348d7f2e76SPhilippe Mathieu-Daudé &timers_state.vm_clock_lock);
1358d7f2e76SPhilippe Mathieu-Daudé }
1368d7f2e76SPhilippe Mathieu-Daudé
icount_state_needed(void * opaque)1378d7f2e76SPhilippe Mathieu-Daudé static bool icount_state_needed(void *opaque)
1388d7f2e76SPhilippe Mathieu-Daudé {
1398d7f2e76SPhilippe Mathieu-Daudé return icount_enabled();
1408d7f2e76SPhilippe Mathieu-Daudé }
1418d7f2e76SPhilippe Mathieu-Daudé
warp_timer_state_needed(void * opaque)1428d7f2e76SPhilippe Mathieu-Daudé static bool warp_timer_state_needed(void *opaque)
1438d7f2e76SPhilippe Mathieu-Daudé {
1448d7f2e76SPhilippe Mathieu-Daudé TimersState *s = opaque;
1458d7f2e76SPhilippe Mathieu-Daudé return s->icount_warp_timer != NULL;
1468d7f2e76SPhilippe Mathieu-Daudé }
1478d7f2e76SPhilippe Mathieu-Daudé
adjust_timers_state_needed(void * opaque)1488d7f2e76SPhilippe Mathieu-Daudé static bool adjust_timers_state_needed(void *opaque)
1498d7f2e76SPhilippe Mathieu-Daudé {
1508d7f2e76SPhilippe Mathieu-Daudé TimersState *s = opaque;
1518d7f2e76SPhilippe Mathieu-Daudé return s->icount_rt_timer != NULL;
1528d7f2e76SPhilippe Mathieu-Daudé }
1538d7f2e76SPhilippe Mathieu-Daudé
icount_shift_state_needed(void * opaque)1548d7f2e76SPhilippe Mathieu-Daudé static bool icount_shift_state_needed(void *opaque)
1558d7f2e76SPhilippe Mathieu-Daudé {
156*8e98c27dSPhilippe Mathieu-Daudé return icount_enabled() == ICOUNT_ADAPTATIVE;
1578d7f2e76SPhilippe Mathieu-Daudé }
1588d7f2e76SPhilippe Mathieu-Daudé
1598d7f2e76SPhilippe Mathieu-Daudé /*
1608d7f2e76SPhilippe Mathieu-Daudé * Subsection for warp timer migration is optional, because may not be created
1618d7f2e76SPhilippe Mathieu-Daudé */
1628d7f2e76SPhilippe Mathieu-Daudé static const VMStateDescription icount_vmstate_warp_timer = {
1638d7f2e76SPhilippe Mathieu-Daudé .name = "timer/icount/warp_timer",
1648d7f2e76SPhilippe Mathieu-Daudé .version_id = 1,
1658d7f2e76SPhilippe Mathieu-Daudé .minimum_version_id = 1,
1668d7f2e76SPhilippe Mathieu-Daudé .needed = warp_timer_state_needed,
16772ecb4a9SRichard Henderson .fields = (const VMStateField[]) {
1688d7f2e76SPhilippe Mathieu-Daudé VMSTATE_INT64(vm_clock_warp_start, TimersState),
1698d7f2e76SPhilippe Mathieu-Daudé VMSTATE_TIMER_PTR(icount_warp_timer, TimersState),
1708d7f2e76SPhilippe Mathieu-Daudé VMSTATE_END_OF_LIST()
1718d7f2e76SPhilippe Mathieu-Daudé }
1728d7f2e76SPhilippe Mathieu-Daudé };
1738d7f2e76SPhilippe Mathieu-Daudé
1748d7f2e76SPhilippe Mathieu-Daudé static const VMStateDescription icount_vmstate_adjust_timers = {
1758d7f2e76SPhilippe Mathieu-Daudé .name = "timer/icount/timers",
1768d7f2e76SPhilippe Mathieu-Daudé .version_id = 1,
1778d7f2e76SPhilippe Mathieu-Daudé .minimum_version_id = 1,
1788d7f2e76SPhilippe Mathieu-Daudé .needed = adjust_timers_state_needed,
17972ecb4a9SRichard Henderson .fields = (const VMStateField[]) {
1808d7f2e76SPhilippe Mathieu-Daudé VMSTATE_TIMER_PTR(icount_rt_timer, TimersState),
1818d7f2e76SPhilippe Mathieu-Daudé VMSTATE_TIMER_PTR(icount_vm_timer, TimersState),
1828d7f2e76SPhilippe Mathieu-Daudé VMSTATE_END_OF_LIST()
1838d7f2e76SPhilippe Mathieu-Daudé }
1848d7f2e76SPhilippe Mathieu-Daudé };
1858d7f2e76SPhilippe Mathieu-Daudé
1868d7f2e76SPhilippe Mathieu-Daudé static const VMStateDescription icount_vmstate_shift = {
1878d7f2e76SPhilippe Mathieu-Daudé .name = "timer/icount/shift",
1888d7f2e76SPhilippe Mathieu-Daudé .version_id = 2,
1898d7f2e76SPhilippe Mathieu-Daudé .minimum_version_id = 2,
1908d7f2e76SPhilippe Mathieu-Daudé .needed = icount_shift_state_needed,
19172ecb4a9SRichard Henderson .fields = (const VMStateField[]) {
1928d7f2e76SPhilippe Mathieu-Daudé VMSTATE_INT16(icount_time_shift, TimersState),
1938d7f2e76SPhilippe Mathieu-Daudé VMSTATE_INT64(last_delta, TimersState),
1948d7f2e76SPhilippe Mathieu-Daudé VMSTATE_END_OF_LIST()
1958d7f2e76SPhilippe Mathieu-Daudé }
1968d7f2e76SPhilippe Mathieu-Daudé };
1978d7f2e76SPhilippe Mathieu-Daudé
1988d7f2e76SPhilippe Mathieu-Daudé /*
1998d7f2e76SPhilippe Mathieu-Daudé * This is a subsection for icount migration.
2008d7f2e76SPhilippe Mathieu-Daudé */
2018d7f2e76SPhilippe Mathieu-Daudé static const VMStateDescription icount_vmstate_timers = {
2028d7f2e76SPhilippe Mathieu-Daudé .name = "timer/icount",
2038d7f2e76SPhilippe Mathieu-Daudé .version_id = 1,
2048d7f2e76SPhilippe Mathieu-Daudé .minimum_version_id = 1,
2058d7f2e76SPhilippe Mathieu-Daudé .needed = icount_state_needed,
20672ecb4a9SRichard Henderson .fields = (const VMStateField[]) {
2078d7f2e76SPhilippe Mathieu-Daudé VMSTATE_INT64(qemu_icount_bias, TimersState),
2088d7f2e76SPhilippe Mathieu-Daudé VMSTATE_INT64(qemu_icount, TimersState),
2098d7f2e76SPhilippe Mathieu-Daudé VMSTATE_END_OF_LIST()
2108d7f2e76SPhilippe Mathieu-Daudé },
21172ecb4a9SRichard Henderson .subsections = (const VMStateDescription * const []) {
2128d7f2e76SPhilippe Mathieu-Daudé &icount_vmstate_warp_timer,
2138d7f2e76SPhilippe Mathieu-Daudé &icount_vmstate_adjust_timers,
2148d7f2e76SPhilippe Mathieu-Daudé &icount_vmstate_shift,
2158d7f2e76SPhilippe Mathieu-Daudé NULL
2168d7f2e76SPhilippe Mathieu-Daudé }
2178d7f2e76SPhilippe Mathieu-Daudé };
2188d7f2e76SPhilippe Mathieu-Daudé
2198d7f2e76SPhilippe Mathieu-Daudé static const VMStateDescription vmstate_timers = {
2208d7f2e76SPhilippe Mathieu-Daudé .name = "timer",
2218d7f2e76SPhilippe Mathieu-Daudé .version_id = 2,
2228d7f2e76SPhilippe Mathieu-Daudé .minimum_version_id = 1,
22372ecb4a9SRichard Henderson .fields = (const VMStateField[]) {
2248d7f2e76SPhilippe Mathieu-Daudé VMSTATE_INT64(cpu_ticks_offset, TimersState),
2258d7f2e76SPhilippe Mathieu-Daudé VMSTATE_UNUSED(8),
2268d7f2e76SPhilippe Mathieu-Daudé VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
2278d7f2e76SPhilippe Mathieu-Daudé VMSTATE_END_OF_LIST()
2288d7f2e76SPhilippe Mathieu-Daudé },
22972ecb4a9SRichard Henderson .subsections = (const VMStateDescription * const []) {
2308d7f2e76SPhilippe Mathieu-Daudé &icount_vmstate_timers,
2318d7f2e76SPhilippe Mathieu-Daudé NULL
2328d7f2e76SPhilippe Mathieu-Daudé }
2338d7f2e76SPhilippe Mathieu-Daudé };
2348d7f2e76SPhilippe Mathieu-Daudé
do_nothing(CPUState * cpu,run_on_cpu_data unused)2358d7f2e76SPhilippe Mathieu-Daudé static void do_nothing(CPUState *cpu, run_on_cpu_data unused)
2368d7f2e76SPhilippe Mathieu-Daudé {
2378d7f2e76SPhilippe Mathieu-Daudé }
2388d7f2e76SPhilippe Mathieu-Daudé
qemu_timer_notify_cb(void * opaque,QEMUClockType type)2398d7f2e76SPhilippe Mathieu-Daudé void qemu_timer_notify_cb(void *opaque, QEMUClockType type)
2408d7f2e76SPhilippe Mathieu-Daudé {
2418d7f2e76SPhilippe Mathieu-Daudé if (!icount_enabled() || type != QEMU_CLOCK_VIRTUAL) {
2428d7f2e76SPhilippe Mathieu-Daudé qemu_notify_event();
2438d7f2e76SPhilippe Mathieu-Daudé return;
2448d7f2e76SPhilippe Mathieu-Daudé }
2458d7f2e76SPhilippe Mathieu-Daudé
2468d7f2e76SPhilippe Mathieu-Daudé if (qemu_in_vcpu_thread()) {
2478d7f2e76SPhilippe Mathieu-Daudé /*
2488d7f2e76SPhilippe Mathieu-Daudé * A CPU is currently running; kick it back out to the
2498d7f2e76SPhilippe Mathieu-Daudé * tcg_cpu_exec() loop so it will recalculate its
2508d7f2e76SPhilippe Mathieu-Daudé * icount deadline immediately.
2518d7f2e76SPhilippe Mathieu-Daudé */
2528d7f2e76SPhilippe Mathieu-Daudé qemu_cpu_kick(current_cpu);
2538d7f2e76SPhilippe Mathieu-Daudé } else if (first_cpu) {
2548d7f2e76SPhilippe Mathieu-Daudé /*
2558d7f2e76SPhilippe Mathieu-Daudé * qemu_cpu_kick is not enough to kick a halted CPU out of
2568d7f2e76SPhilippe Mathieu-Daudé * qemu_tcg_wait_io_event. async_run_on_cpu, instead,
2578d7f2e76SPhilippe Mathieu-Daudé * causes cpu_thread_is_idle to return false. This way,
2588d7f2e76SPhilippe Mathieu-Daudé * handle_icount_deadline can run.
2598d7f2e76SPhilippe Mathieu-Daudé * If we have no CPUs at all for some reason, we don't
2608d7f2e76SPhilippe Mathieu-Daudé * need to do anything.
2618d7f2e76SPhilippe Mathieu-Daudé */
2628d7f2e76SPhilippe Mathieu-Daudé async_run_on_cpu(first_cpu, do_nothing, RUN_ON_CPU_NULL);
2638d7f2e76SPhilippe Mathieu-Daudé }
2648d7f2e76SPhilippe Mathieu-Daudé }
2658d7f2e76SPhilippe Mathieu-Daudé
2668d7f2e76SPhilippe Mathieu-Daudé TimersState timers_state;
2678d7f2e76SPhilippe Mathieu-Daudé
2688d7f2e76SPhilippe Mathieu-Daudé /* initialize timers state and the cpu throttle for convenience */
cpu_timers_init(void)2698d7f2e76SPhilippe Mathieu-Daudé void cpu_timers_init(void)
2708d7f2e76SPhilippe Mathieu-Daudé {
2718d7f2e76SPhilippe Mathieu-Daudé seqlock_init(&timers_state.vm_clock_seqlock);
2728d7f2e76SPhilippe Mathieu-Daudé qemu_spin_init(&timers_state.vm_clock_lock);
2738d7f2e76SPhilippe Mathieu-Daudé vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
2748d7f2e76SPhilippe Mathieu-Daudé }
275