@@ -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;
}
@@ -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
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 <cov@codeaurora.org> --- cpus.c | 17 +++++++++++++---- target-arm/helper.c | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-)