@@ -1179,47 +1179,64 @@ static void handle_icount_deadline(void)
}
}
-static int tcg_cpu_exec(CPUState *cpu)
+static void prepare_icount_for_run(CPUState *cpu)
{
- int ret;
-#ifdef CONFIG_PROFILER
- int64_t ti;
-#endif
-
-#ifdef CONFIG_PROFILER
- ti = profile_getclock();
-#endif
if (use_icount) {
int64_t count;
int decr;
- timers_state.qemu_icount -= (cpu->icount_decr.u16.low
- + cpu->icount_extra);
- cpu->icount_decr.u16.low = 0;
- cpu->icount_extra = 0;
+
+ /* These should always be cleared by process_icount_data after
+ * each vCPU execution. However u16.high can be raised
+ * asynchronously by cpu_exit/cpu_interrupt/tcg_handle_interrupt
+ */
+ g_assert(cpu->icount_decr.u16.low == 0);
+ g_assert(cpu->icount_extra == 0);
+
+
count = tcg_get_icount_limit();
+
timers_state.qemu_icount += count;
decr = (count > 0xffff) ? 0xffff : count;
count -= decr;
cpu->icount_decr.u16.low = decr;
cpu->icount_extra = count;
}
- qemu_mutex_unlock_iothread();
- cpu_exec_start(cpu);
- ret = cpu_exec(cpu);
- cpu_exec_end(cpu);
- qemu_mutex_lock_iothread();
-#ifdef CONFIG_PROFILER
- tcg_time += profile_getclock() - ti;
-#endif
+}
+
+static void process_icount_data(CPUState *cpu)
+{
if (use_icount) {
/* Fold pending instructions back into the
instruction counter, and clear the interrupt flag. */
timers_state.qemu_icount -= (cpu->icount_decr.u16.low
+ cpu->icount_extra);
- cpu->icount_decr.u32 = 0;
+
+ /* Reset the counters */
+ cpu->icount_decr.u16.low = 0;
cpu->icount_extra = 0;
replay_account_executed_instructions();
}
+}
+
+
+static int tcg_cpu_exec(CPUState *cpu)
+{
+ int ret;
+#ifdef CONFIG_PROFILER
+ int64_t ti;
+#endif
+
+#ifdef CONFIG_PROFILER
+ ti = profile_getclock();
+#endif
+ qemu_mutex_unlock_iothread();
+ cpu_exec_start(cpu);
+ ret = cpu_exec(cpu);
+ cpu_exec_end(cpu);
+ qemu_mutex_lock_iothread();
+#ifdef CONFIG_PROFILER
+ tcg_time += profile_getclock() - ti;
+#endif
return ret;
}
@@ -1306,7 +1323,13 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)
if (cpu_can_run(cpu)) {
int r;
+
+ prepare_icount_for_run(cpu);
+
r = tcg_cpu_exec(cpu);
+
+ process_icount_data(cpu);
+
if (r == EXCP_DEBUG) {
cpu_handle_guest_debug(cpu);
break;
As icount is only supported for single-threaded execution due to the requirement for determinism let's remove it from the common tcg_exec_cpu path. Also remove the additional fiddling which shouldn't be required as the icount counters should all be rectified as you enter the loop. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> -- 2.11.0