* [PATCH v2 1/2] qemu/timer: introduce time dilation factor
2025-06-28 0:24 [PATCH v2 0/2] control guest time using a dilation factor Pierrick Bouvier
@ 2025-06-28 0:24 ` Pierrick Bouvier
2025-06-28 0:24 ` [PATCH v2 2/2] system/rtc: introduce -rtc speed-factor option Pierrick Bouvier
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Pierrick Bouvier @ 2025-06-28 0:24 UTC (permalink / raw)
To: qemu-devel
Cc: berrange, richard.henderson, Paolo Bonzini, Alex Bennée,
Thomas Huth, peter.maydell, philmd, Pierrick Bouvier
This factor is applied to time spent since we initialized clocks.
It impacts value returned by get_clock(), get_clock_realtime() and
get_cpu_host_ticks();
< 1: time goes slower.
> 1: time goes faster.
1 by default.
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
---
include/qemu/timer.h | 60 ++++++++++++++++++++++++++++------------
util/qemu-timer-common.c | 7 +++++
2 files changed, 49 insertions(+), 18 deletions(-)
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index abd2204f3be..ee1877d5cd9 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -801,6 +801,23 @@ static inline int64_t get_max_clock_jump(void)
return 60 * NANOSECONDS_PER_SECOND;
}
+extern int64_t clock_start;
+extern int64_t clock_realtime_start;
+extern int64_t host_ticks_start;
+extern double clock_time_dilation;
+
+static inline int64_t dilate_time(int64_t start, int64_t now)
+{
+ if (start == 0) {
+ /* start value is getting fetched */
+ return now;
+ }
+ g_assert(now >= start);
+ int64_t elapsed = now - start;
+ int64_t elapsed_dilated = elapsed * clock_time_dilation;
+ return start + elapsed_dilated;
+}
+
/*
* Low level clock functions
*/
@@ -811,11 +828,10 @@ static inline int64_t get_clock_realtime(void)
struct timeval tv;
gettimeofday(&tv, NULL);
- return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
+ int64_t now = tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
+ return dilate_time(clock_realtime_start, now);
}
-extern int64_t clock_start;
-
/* Warning: don't insert tracepoints into these functions, they are
also used by simpletrace backend and tracepoints would cause
an infinite recursion! */
@@ -826,7 +842,8 @@ static inline int64_t get_clock(void)
{
LARGE_INTEGER ti;
QueryPerformanceCounter(&ti);
- return muldiv64(ti.QuadPart, NANOSECONDS_PER_SECOND, clock_freq);
+ int64_t now = muldiv64(ti.QuadPart, NANOSECONDS_PER_SECOND, clock_freq);
+ return dilate_time(clock_start, now);
}
#else
@@ -838,10 +855,11 @@ static inline int64_t get_clock(void)
if (use_rt_clock) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
- return ts.tv_sec * 1000000000LL + ts.tv_nsec;
+ int64_t now = ts.tv_sec * 1000000000LL + ts.tv_nsec;
+ return dilate_time(clock_start, now);
} else {
/* XXX: using gettimeofday leads to problems if the date
- changes, so it should be avoided. */
+ changes, so it should be avoided. Time is already dilated. */
return get_clock_realtime();
}
}
@@ -852,7 +870,7 @@ static inline int64_t get_clock(void)
#if defined(_ARCH_PPC)
-static inline int64_t cpu_get_host_ticks(void)
+static inline int64_t _cpu_get_host_ticks(void)
{
int64_t retval;
#ifdef _ARCH_PPC64
@@ -878,7 +896,7 @@ static inline int64_t cpu_get_host_ticks(void)
#elif defined(__i386__)
-static inline int64_t cpu_get_host_ticks(void)
+static inline int64_t _cpu_get_host_ticks(void)
{
int64_t val;
asm volatile ("rdtsc" : "=A" (val));
@@ -887,7 +905,7 @@ static inline int64_t cpu_get_host_ticks(void)
#elif defined(__x86_64__)
-static inline int64_t cpu_get_host_ticks(void)
+static inline int64_t _cpu_get_host_ticks(void)
{
uint32_t low,high;
int64_t val;
@@ -900,7 +918,7 @@ static inline int64_t cpu_get_host_ticks(void)
#elif defined(__hppa__)
-static inline int64_t cpu_get_host_ticks(void)
+static inline int64_t _cpu_get_host_ticks(void)
{
int val;
asm volatile ("mfctl %%cr16, %0" : "=r"(val));
@@ -909,7 +927,7 @@ static inline int64_t cpu_get_host_ticks(void)
#elif defined(__s390__)
-static inline int64_t cpu_get_host_ticks(void)
+static inline int64_t _cpu_get_host_ticks(void)
{
int64_t val;
asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
@@ -918,7 +936,7 @@ static inline int64_t cpu_get_host_ticks(void)
#elif defined(__sparc__)
-static inline int64_t cpu_get_host_ticks (void)
+static inline int64_t _cpu_get_host_ticks(void)
{
#if defined(_LP64)
uint64_t rval;
@@ -956,7 +974,7 @@ static inline int64_t cpu_get_host_ticks (void)
: "=r" (value)); \
}
-static inline int64_t cpu_get_host_ticks(void)
+static inline int64_t _cpu_get_host_ticks(void)
{
/* On kernels >= 2.6.25 rdhwr <reg>, $2 and $3 are emulated */
uint32_t count;
@@ -972,7 +990,7 @@ static inline int64_t cpu_get_host_ticks(void)
#elif defined(__alpha__)
-static inline int64_t cpu_get_host_ticks(void)
+static inline int64_t _cpu_get_host_ticks(void)
{
uint64_t cc;
uint32_t cur, ofs;
@@ -984,7 +1002,7 @@ static inline int64_t cpu_get_host_ticks(void)
}
#elif defined(__riscv) && __riscv_xlen == 32
-static inline int64_t cpu_get_host_ticks(void)
+static inline int64_t _cpu_get_host_ticks(void)
{
uint32_t lo, hi, tmph;
do {
@@ -997,7 +1015,7 @@ static inline int64_t cpu_get_host_ticks(void)
}
#elif defined(__riscv) && __riscv_xlen > 32
-static inline int64_t cpu_get_host_ticks(void)
+static inline int64_t _cpu_get_host_ticks(void)
{
int64_t val;
@@ -1006,7 +1024,7 @@ static inline int64_t cpu_get_host_ticks(void)
}
#elif defined(__loongarch64)
-static inline int64_t cpu_get_host_ticks(void)
+static inline int64_t _cpu_get_host_ticks(void)
{
uint64_t val;
@@ -1018,10 +1036,16 @@ static inline int64_t cpu_get_host_ticks(void)
/* The host CPU doesn't have an easily accessible cycle counter.
Just return a monotonically increasing value. This will be
totally wrong, but hopefully better than nothing. */
-static inline int64_t cpu_get_host_ticks(void)
+static inline int64_t _cpu_get_host_ticks(void)
{
return get_clock();
}
#endif
+static inline int64_t cpu_get_host_ticks(void)
+{
+ int64_t now = _cpu_get_host_ticks();
+ return dilate_time(host_ticks_start, now);
+}
+
#endif
diff --git a/util/qemu-timer-common.c b/util/qemu-timer-common.c
index cc1326f7264..5cb36032bc8 100644
--- a/util/qemu-timer-common.c
+++ b/util/qemu-timer-common.c
@@ -28,6 +28,9 @@
/* real time host monotonic timer */
int64_t clock_start;
+int64_t clock_realtime_start;
+int64_t host_ticks_start;
+double clock_time_dilation = 1.0f;
#ifdef _WIN32
@@ -44,6 +47,8 @@ static void __attribute__((constructor)) init_get_clock(void)
}
clock_freq = freq.QuadPart;
clock_start = get_clock();
+ clock_realtime_start = get_clock_realtime();
+ host_ticks_start = cpu_get_host_ticks();
}
#else
@@ -59,5 +64,7 @@ static void __attribute__((constructor)) init_get_clock(void)
use_rt_clock = 1;
}
clock_start = get_clock();
+ clock_realtime_start = get_clock_realtime();
+ host_ticks_start = cpu_get_host_ticks();
}
#endif
--
2.47.2
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 2/2] system/rtc: introduce -rtc speed-factor option
2025-06-28 0:24 [PATCH v2 0/2] control guest time using a dilation factor Pierrick Bouvier
2025-06-28 0:24 ` [PATCH v2 1/2] qemu/timer: introduce time " Pierrick Bouvier
@ 2025-06-28 0:24 ` Pierrick Bouvier
2025-07-08 17:43 ` [PATCH v2 0/2] control guest time using a dilation factor Pierrick Bouvier
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Pierrick Bouvier @ 2025-06-28 0:24 UTC (permalink / raw)
To: qemu-devel
Cc: berrange, richard.henderson, Paolo Bonzini, Alex Bennée,
Thomas Huth, peter.maydell, philmd, Pierrick Bouvier
This option sets a factor on time spent for QEMU clocks since the
beginning of execution. It can be used to slow or accelerate time for a
guest, without impacting QEMU speed.
It can only be used with tcg.
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
---
system/rtc.c | 11 +++++++++++
system/vl.c | 9 +++++++++
qemu-options.hx | 7 ++++++-
3 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/system/rtc.c b/system/rtc.c
index 56951288c40..ec063391b5c 100644
--- a/system/rtc.c
+++ b/system/rtc.c
@@ -188,4 +188,15 @@ void configure_rtc(QemuOpts *opts)
exit(1);
}
}
+ value = qemu_opt_get(opts, "speed-factor");
+ if (value) {
+ if (qemu_strtod_finite(value, NULL, &clock_time_dilation)) {
+ error_report("invalid speed-factor factor '%s'", value);
+ exit(1);
+ }
+ if (clock_time_dilation <= 0.0f) {
+ error_report("speed-factor factor must be strictly positive");
+ exit(1);
+ }
+ }
}
diff --git a/system/vl.c b/system/vl.c
index 3b7057e6c66..e1ea79c683c 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -243,6 +243,9 @@ static QemuOptsList qemu_rtc_opts = {
},{
.name = "driftfix",
.type = QEMU_OPT_STRING,
+ },{
+ .name = "speed-factor",
+ .type = QEMU_OPT_STRING,
},
{ /* end of list */ }
},
@@ -2491,6 +2494,12 @@ static void configure_accelerators(const char *progname)
error_report("-icount is not allowed with hardware virtualization");
exit(1);
}
+
+ if (clock_time_dilation != 1.0f && !tcg_enabled()) {
+ error_report("-rtc speed-factor is not allowed with "
+ "hardware virtualization");
+ exit(1);
+ }
}
static void qemu_validate_options(const QDict *machine_opts)
diff --git a/qemu-options.hx b/qemu-options.hx
index 6bcbb8ccea0..9efdbfb3842 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4887,7 +4887,7 @@ SRST
ERST
DEF("rtc", HAS_ARG, QEMU_OPTION_rtc, \
- "-rtc [base=utc|localtime|<datetime>][,clock=host|rt|vm][,driftfix=none|slew]\n" \
+ "-rtc [base=utc|localtime|<datetime>][,clock=host|rt|vm][,driftfix=none|slew][,speed-factor=value]\n" \
" set the RTC base and clock, enable drift fix for clock ticks (x86 only)\n",
QEMU_ARCH_ALL)
@@ -4916,6 +4916,11 @@ SRST
problems, specifically with Windows' ACPI HAL. This option will try
to figure out how many timer interrupts were not processed by the
Windows guest and will re-inject them.
+
+ It's possible to slow or accelerate time using ``speed-factor``,
+ which is a factor (real number) applied to QEMU clock. A value of 0.1 will
+ slow time by a factor of 10, and a value of 10 will accelerate it with the
+ same factor.
ERST
DEF("icount", HAS_ARG, QEMU_OPTION_icount, \
--
2.47.2
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH v2 0/2] control guest time using a dilation factor
2025-06-28 0:24 [PATCH v2 0/2] control guest time using a dilation factor Pierrick Bouvier
2025-06-28 0:24 ` [PATCH v2 1/2] qemu/timer: introduce time " Pierrick Bouvier
2025-06-28 0:24 ` [PATCH v2 2/2] system/rtc: introduce -rtc speed-factor option Pierrick Bouvier
@ 2025-07-08 17:43 ` Pierrick Bouvier
2025-07-21 16:42 ` Pierrick Bouvier
2025-08-04 16:19 ` Pierrick Bouvier
4 siblings, 0 replies; 6+ messages in thread
From: Pierrick Bouvier @ 2025-07-08 17:43 UTC (permalink / raw)
To: qemu-devel
Cc: berrange, richard.henderson, Paolo Bonzini, Alex Bennée,
Thomas Huth, peter.maydell, philmd
On 6/27/25 5:24 PM, Pierrick Bouvier wrote:
> Depending on host cpu speed, and QEMU optimization level, it may sometimes be
> needed to slow or accelerate time guest is perceiving. A common scenario is
> hitting a timeout during a boot process, because some operations were not
> finished on time.
>
> An existing solution for that is -icount shift=X, with low values, which will
> roughly map virtual time to how many instructions were executed.
>
> This series introduces another approach, based on faking host time returned to
> the guest, by applying a time-dilation factor. Time will go slower/faster for
> the guest, without impacting QEMU emulation speed.
>
> It may eventually be used to fix some of the timeouts we hit in CI, by slowing
> down time in VM, to be less sensitive to varying cpu performance.
>
> v2
> --
>
> In review, Paolo mentioned timers deadline should redilated in the other
> direction. After going through this part, it seems that arrival is always based
> on one of the clocks we have (which is dilated already), so I don't think we
> should redilate that, as this would create a discordance between time set, and
> real time when this happen. Feel free to correct me if this is wrong.
>
> - keep start time per clock and apply accordingly
> - apply time dilation for cpu_get_host_ticks as well
> - use a default factor of 1.0
> - rename cli option to -rtc speed-factor
> - forbid to use option with kvm, as time is not provided by QEMU for guest
>
> Pierrick Bouvier (2):
> qemu/timer: introduce time dilation factor
> system/rtc: introduce -rtc speed-factor option
>
> include/qemu/timer.h | 60 ++++++++++++++++++++++++++++------------
> system/rtc.c | 11 ++++++++
> system/vl.c | 9 ++++++
> util/qemu-timer-common.c | 7 +++++
> qemu-options.hx | 7 ++++-
> 5 files changed, 75 insertions(+), 19 deletions(-)
>
Gentle ping on this series.
Regards,
Pierrick
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 0/2] control guest time using a dilation factor
2025-06-28 0:24 [PATCH v2 0/2] control guest time using a dilation factor Pierrick Bouvier
` (2 preceding siblings ...)
2025-07-08 17:43 ` [PATCH v2 0/2] control guest time using a dilation factor Pierrick Bouvier
@ 2025-07-21 16:42 ` Pierrick Bouvier
2025-08-04 16:19 ` Pierrick Bouvier
4 siblings, 0 replies; 6+ messages in thread
From: Pierrick Bouvier @ 2025-07-21 16:42 UTC (permalink / raw)
To: qemu-devel
Cc: berrange, richard.henderson, Paolo Bonzini, Alex Bennée,
Thomas Huth, peter.maydell, philmd
On 6/27/25 5:24 PM, Pierrick Bouvier wrote:
> Depending on host cpu speed, and QEMU optimization level, it may sometimes be
> needed to slow or accelerate time guest is perceiving. A common scenario is
> hitting a timeout during a boot process, because some operations were not
> finished on time.
>
> An existing solution for that is -icount shift=X, with low values, which will
> roughly map virtual time to how many instructions were executed.
>
> This series introduces another approach, based on faking host time returned to
> the guest, by applying a time-dilation factor. Time will go slower/faster for
> the guest, without impacting QEMU emulation speed.
>
> It may eventually be used to fix some of the timeouts we hit in CI, by slowing
> down time in VM, to be less sensitive to varying cpu performance.
>
> v2
> --
>
> In review, Paolo mentioned timers deadline should redilated in the other
> direction. After going through this part, it seems that arrival is always based
> on one of the clocks we have (which is dilated already), so I don't think we
> should redilate that, as this would create a discordance between time set, and
> real time when this happen. Feel free to correct me if this is wrong.
>
> - keep start time per clock and apply accordingly
> - apply time dilation for cpu_get_host_ticks as well
> - use a default factor of 1.0
> - rename cli option to -rtc speed-factor
> - forbid to use option with kvm, as time is not provided by QEMU for guest
>
> Pierrick Bouvier (2):
> qemu/timer: introduce time dilation factor
> system/rtc: introduce -rtc speed-factor option
>
> include/qemu/timer.h | 60 ++++++++++++++++++++++++++++------------
> system/rtc.c | 11 ++++++++
> system/vl.c | 9 ++++++
> util/qemu-timer-common.c | 7 +++++
> qemu-options.hx | 7 ++++-
> 5 files changed, 75 insertions(+), 19 deletions(-)
>
Another ping on this series.
Paolo, do you have any opinion about the comment in v2 I added in the
cover letter? Especially to not modify the arrival date for timers.
Thanks,
Pierrick
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH v2 0/2] control guest time using a dilation factor
2025-06-28 0:24 [PATCH v2 0/2] control guest time using a dilation factor Pierrick Bouvier
` (3 preceding siblings ...)
2025-07-21 16:42 ` Pierrick Bouvier
@ 2025-08-04 16:19 ` Pierrick Bouvier
4 siblings, 0 replies; 6+ messages in thread
From: Pierrick Bouvier @ 2025-08-04 16:19 UTC (permalink / raw)
To: qemu-devel
Cc: berrange, richard.henderson, Paolo Bonzini, Alex Bennée,
Thomas Huth, peter.maydell, philmd
On 6/27/25 5:24 PM, Pierrick Bouvier wrote:
> Depending on host cpu speed, and QEMU optimization level, it may sometimes be
> needed to slow or accelerate time guest is perceiving. A common scenario is
> hitting a timeout during a boot process, because some operations were not
> finished on time.
>
> An existing solution for that is -icount shift=X, with low values, which will
> roughly map virtual time to how many instructions were executed.
>
> This series introduces another approach, based on faking host time returned to
> the guest, by applying a time-dilation factor. Time will go slower/faster for
> the guest, without impacting QEMU emulation speed.
>
> It may eventually be used to fix some of the timeouts we hit in CI, by slowing
> down time in VM, to be less sensitive to varying cpu performance.
>
> v2
> --
>
> In review, Paolo mentioned timers deadline should redilated in the other
> direction. After going through this part, it seems that arrival is always based
> on one of the clocks we have (which is dilated already), so I don't think we
> should redilate that, as this would create a discordance between time set, and
> real time when this happen. Feel free to correct me if this is wrong.
>
> - keep start time per clock and apply accordingly
> - apply time dilation for cpu_get_host_ticks as well
> - use a default factor of 1.0
> - rename cli option to -rtc speed-factor
> - forbid to use option with kvm, as time is not provided by QEMU for guest
>
> Pierrick Bouvier (2):
> qemu/timer: introduce time dilation factor
> system/rtc: introduce -rtc speed-factor option
>
> include/qemu/timer.h | 60 ++++++++++++++++++++++++++++------------
> system/rtc.c | 11 ++++++++
> system/vl.c | 9 ++++++
> util/qemu-timer-common.c | 7 +++++
> qemu-options.hx | 7 ++++-
> 5 files changed, 75 insertions(+), 19 deletions(-)
>
Trying another ping on this series.
It has been useful to reduce number of interruptions in a guest when
running on a slow machine.
Regards,
Pierrick
^ permalink raw reply [flat|nested] 6+ messages in thread