xref: /openbmc/qemu/system/cpu-timers.c (revision cbad45511840077dafb6e1d1bc2e228baabecff5)
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