From 05248382251a58a14da60a640d29f570524174d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 29 Mar 2017 16:46:59 +0100 Subject: [PATCH] cpus: move icount preparation out of tcg_exec_cpu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- cpus.c | 69 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/cpus.c b/cpus.c index 7ec6473c02..6034b104c3 100644 --- a/cpus.c +++ b/cpus.c @@ -1179,6 +1179,46 @@ static void handle_icount_deadline(void) } } +static void prepare_icount_for_run(CPUState *cpu) +{ + if (use_icount) { + int64_t count; + int decr; + + /* 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; + } +} + +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); + + /* 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; @@ -1189,20 +1229,6 @@ static int tcg_cpu_exec(CPUState *cpu) #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; - 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); @@ -1211,15 +1237,6 @@ static int tcg_cpu_exec(CPUState *cpu) #ifdef CONFIG_PROFILER tcg_time += profile_getclock() - ti; #endif - 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; - cpu->icount_extra = 0; - replay_account_executed_instructions(); - } 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;