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.bouv...@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


Reply via email to