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
© 2016 - 2025 Red Hat, Inc.