From: KONRAD Frederic <fred.kon...@greensocs.com> This introduces a new timer based only on instruction counter and without any compensation.
Signed-off-by: KONRAD Frederic <fred.kon...@greensocs.com> --- cpus.c | 28 +++++++++++++++++++++++----- include/qemu/timer.h | 8 ++++++++ qemu-timer.c | 6 ++++++ stubs/cpu-get-icount.c | 5 +++++ 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/cpus.c b/cpus.c index bdbc431..ba096a3 100644 --- a/cpus.c +++ b/cpus.c @@ -132,7 +132,7 @@ typedef struct TimersState { static TimersState timers_state; /* Return the virtual CPU time, based on the instruction counter. */ -static int64_t cpu_get_icount_locked(void) +static int64_t cpu_get_icount_locked(int with_bias) { int64_t icount; CPUState *cpu = current_cpu; @@ -144,7 +144,12 @@ static int64_t cpu_get_icount_locked(void) } icount -= (cpu->icount_decr.u16.low + cpu->icount_extra); } - return timers_state.qemu_icount_bias + (icount << icount_time_shift); + + if (with_bias) { + return timers_state.qemu_icount_bias + (icount << icount_time_shift); + } else { + return icount << icount_time_shift; + } } int64_t cpu_get_icount(void) @@ -154,7 +159,20 @@ int64_t cpu_get_icount(void) do { start = seqlock_read_begin(&timers_state.vm_clock_seqlock); - icount = cpu_get_icount_locked(); + icount = cpu_get_icount_locked(true); + } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); + + return icount; +} + +int64_t cpu_get_icount_wo_bias(void) +{ + int64_t icount; + unsigned start; + + do { + start = seqlock_read_begin(&timers_state.vm_clock_seqlock); + icount = cpu_get_icount_locked(false); } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start)); return icount; @@ -265,7 +283,7 @@ static void icount_adjust(void) seqlock_write_lock(&timers_state.vm_clock_seqlock); cur_time = cpu_get_clock_locked(); - cur_icount = cpu_get_icount_locked(); + cur_icount = cpu_get_icount_locked(true); delta = cur_icount - cur_time; /* FIXME: This is a very crude algorithm, somewhat prone to oscillation. */ @@ -328,7 +346,7 @@ static void icount_warp_rt(void *opaque) * far ahead of real time. */ int64_t cur_time = cpu_get_clock_locked(); - int64_t cur_icount = cpu_get_icount_locked(); + int64_t cur_icount = cpu_get_icount_locked(true); int64_t delta = cur_time - cur_icount; warp_delta = MIN(warp_delta, delta); } diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 7f9a074..da47194 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -36,12 +36,19 @@ * is suspended, and it will reflect system time changes the host may * undergo (e.g. due to NTP). The host clock has the same precision as * the virtual clock. + * + * @QEMU_CLOCK_ICOUNT: icount clock + * + * The icount clock is based on instruction counter without any compensation for + * speed. It will run only when instruction are executed and make only sense in + * icount mode. */ typedef enum { QEMU_CLOCK_REALTIME = 0, QEMU_CLOCK_VIRTUAL = 1, QEMU_CLOCK_HOST = 2, + QEMU_CLOCK_ICOUNT = 3, QEMU_CLOCK_MAX } QEMUClockType; @@ -743,6 +750,7 @@ static inline int64_t get_clock(void) #endif /* icount */ +int64_t cpu_get_icount_wo_bias(void); int64_t cpu_get_icount(void); int64_t cpu_get_clock(void); diff --git a/qemu-timer.c b/qemu-timer.c index e15ce47..8a36906 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -563,6 +563,12 @@ int64_t qemu_clock_get_ns(QEMUClockType type) notifier_list_notify(&clock->reset_notifiers, &now); } return now; + case QEMU_CLOCK_ICOUNT: + if (use_icount) { + return cpu_get_icount_wo_bias(); + } else { + return -1; + } } } diff --git a/stubs/cpu-get-icount.c b/stubs/cpu-get-icount.c index d685859..fa242f3 100644 --- a/stubs/cpu-get-icount.c +++ b/stubs/cpu-get-icount.c @@ -7,3 +7,8 @@ int64_t cpu_get_icount(void) { abort(); } + +int64_t cpu_get_icount_wo_bias(void) +{ + abort(); +} -- 1.8.1.4