From c52e7132d7c885841500f5277f7305f62767fe1d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 10 Apr 2018 13:02:25 +0100 Subject: cpus.c: ensure running CPU recalculates icount deadlines on timer expiry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we run in TCG icount mode, we calculate the number of instructions to execute using tcg_get_icount_limit(), which ensures that we stop execution at the next timer deadline. However there is a bug where currently we do not recalculate that limit if the guest reprograms a timer so that the next deadline moves closer, and so we will continue execution until the original limit and fire the timer later than we should. Fix this bug in qemu_timer_notify_cb(): if we are currently running a VCPU in icount mode, we simply need to kick it out of the main loop and back to tcg_cpu_exec(), where it will recalculate the icount limit. If we are not currently running a VCPU, then we retain the existing logic for waking up a halted CPU. Cc: qemu-stable@nongnu.org Fixes: https://bugs.launchpad.net/qemu/+bug/1754038 Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Message-id: 20180406123838.21249-1-peter.maydell@linaro.org --- cpus.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cpus.c b/cpus.c index 2e6701795b..38eba8bff3 100644 --- a/cpus.c +++ b/cpus.c @@ -892,11 +892,19 @@ void qemu_timer_notify_cb(void *opaque, QEMUClockType type) return; } - if (!qemu_in_vcpu_thread() && first_cpu) { + if (qemu_in_vcpu_thread()) { + /* A CPU is currently running; kick it back out to the + * tcg_cpu_exec() loop so it will recalculate its + * icount deadline immediately. + */ + qemu_cpu_kick(current_cpu); + } else if (first_cpu) { /* qemu_cpu_kick is not enough to kick a halted CPU out of * qemu_tcg_wait_io_event. async_run_on_cpu, instead, * causes cpu_thread_is_idle to return false. This way, * handle_icount_deadline can run. + * If we have no CPUs at all for some reason, we don't + * need to do anything. */ async_run_on_cpu(first_cpu, do_nothing, RUN_ON_CPU_NULL); } -- cgit v1.2.3