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