* [PATCH v2 0/2] control guest time using a dilation factor
@ 2025-06-28 0:24 Pierrick Bouvier
2025-06-28 0:24 ` [PATCH v2 1/2] qemu/timer: introduce time " Pierrick Bouvier
` (4 more replies)
0 siblings, 5 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
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(-)
--
2.47.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* [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
end of thread, other threads:[~2025-08-04 18:26 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [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
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).