The icount setting specifies how far to shift the instruction count as a ratio of ns to tie system time to instruction count. Allow a negative value (i.e. a right shift instead of a left shift) to be used.
Written by Pat Galizia. Signed-off-by: Christopher Covington <c...@codeaurora.org> --- cpus.c | 17 +++++++++++++---- target-arm/helper.c | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/cpus.c b/cpus.c index 62d157a..1c92a85 100644 --- a/cpus.c +++ b/cpus.c @@ -110,6 +110,8 @@ static int64_t vm_clock_warp_start = -1; static int icount_time_shift; /* Arbitrarily pick 1MIPS as the minimum allowable speed. */ #define MAX_ICOUNT_SHIFT 10 +/* In cases where we have a negative icount shift, specify a lower bound. */ +#define MIN_ICOUNT_SHIFT -5 static QEMUTimer *icount_rt_timer; static QEMUTimer *icount_vm_timer; @@ -174,6 +176,8 @@ int64_t cpu_get_icount(void) int64_t cpu_icount_to_ns(int64_t icount) { + if (icount_time_shift < 0) + return icount >> (-icount_time_shift); return icount << icount_time_shift; } @@ -271,6 +275,7 @@ static void icount_adjust(void) int64_t cur_time; int64_t cur_icount; int64_t delta; + int64_t icount_shifted; /* Protected by TimersState mutex. */ static int64_t last_delta; @@ -287,8 +292,8 @@ static void icount_adjust(void) delta = cur_icount - cur_time; /* FIXME: This is a very crude algorithm, somewhat prone to oscillation. */ if (delta > 0 - && last_delta + ICOUNT_WOBBLE < delta * 2 - && icount_time_shift > 0) { + && last_delta + ICOUNT_WOBBLE < delta * 2 + && icount_time_shift > MIN_ICOUNT_SHIFT) { /* The guest is getting too far ahead. Slow time down. */ icount_time_shift--; } @@ -299,8 +304,10 @@ static void icount_adjust(void) icount_time_shift++; } last_delta = delta; - timers_state.qemu_icount_bias = cur_icount - - (timers_state.qemu_icount << icount_time_shift); + icount_shifted = (icount_time_shift >= 0) ? + timers_state.qemu_icount << icount_time_shift : + timers_state.qemu_icount >> (-icount_time_shift); + timers_state.qemu_icount_bias = cur_icount - icount_shifted; seqlock_write_unlock(&timers_state.vm_clock_seqlock); } @@ -321,6 +328,8 @@ static void icount_adjust_vm(void *opaque) static int64_t qemu_icount_round(int64_t count) { + if (icount_time_shift < 0) + return count; return (count + (1 << icount_time_shift) - 1) >> icount_time_shift; } diff --git a/target-arm/helper.c b/target-arm/helper.c index ae0a4ac..0436df5 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -4345,6 +4345,11 @@ void context_check_pid(CPUARMState *env) void update_instruction_count(CPUARMState *env) { + CPUState *cpu = CPU(arm_env_get_cpu(env)); + int prevIoState = cpu->can_do_io; + if (use_icount) + cpu->can_do_io = 1; + if (bbtrace_initialized()) { /* * If the bbv plugin is compiled in and enabled, we must account for the @@ -4368,15 +4373,24 @@ void update_instruction_count(CPUARMState *env) pmevcntr_increment(env, PMU_COUNTER_TYPE_CYCLES, env->prof_ic); env->prof_ic = 0; } + + if (use_icount) + cpu->can_do_io = prevIoState; } #else //!CONFIG_BBVEC void update_instruction_count(CPUARMState *env) { + CPUState *cpu = CPU(arm_env_get_cpu(env)); + int prevIoState = cpu->can_do_io; + if (use_icount) + cpu->can_do_io = 1; pmevcntr_increment(env, PMU_COUNTER_TYPE_INSTRUCTIONS, env->prof_ic); pmevcntr_increment(env, PMU_COUNTER_TYPE_CYCLES, env->prof_ic); env->prof_ic = 0; + if (use_icount) + cpu->can_do_io = prevIoState; } #endif //CONFIG_BBVEC -- Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project