Skip to content

Commit 02ae315

Browse files
committed
util/qemu-timer.c: Don't warp timer from timerlist_rearm()
Currently we call icount_start_warp_timer() from timerlist_rearm(). This produces incorrect behaviour, because timerlist_rearm() is called, for instance, when a timer callback modifies its timer. We cannot decide here to warp the timer forwards to the next timer deadline merely because all_cpu_threads_idle() is true, because the timer callback we were called from (or some other callback later in the list of callbacks being invoked) may be about to raise a CPU interrupt and move a CPU from idle to ready. The only valid place to choose to warp the timer forward is from the main loop, when we know we have no outstanding IO or timer callbacks that might be about to wake up a CPU. For Arm guests, this bug was mostly latent until the refactoring commit f6fc36d ("target/arm/helper: Implement CNTHCTL_EL2.CNT[VP]MASK"), which exposed it because it refactored a timer callback so that it happened to call timer_mod() first and raise the interrupt second, when it had previously raised the interrupt first and called timer_mod() afterwards. This call seems to have originally derived from the pre-record-and-replay icount code, which (as of e.g. commit db1a497 in 2010) in this location did a call to qemu_notify_event(), necessary to get the icount code in the vCPU round-robin thread to stop and recalculate the icount deadline when a timer was reprogrammed from the IO thread. In current QEMU, everything is done on the vCPU thread when we are in icount mode, so there's no need to try to notify another thread here. I suspect that the other reason why this call was doing icount timer warping is that it pre-dates commit efab87c from 2015, which added a call to icount_start_warp_timer() to main_loop_wait(). Once the call in timerlist_rearm() has been removed, if the timer callbacks don't cause any CPU to be woken up then we will end up calling icount_start_warp_timer() from main_loop_wait() when the rr main loop code calls rr_wait_io_event(). Remove the incorrect call from timerlist_rearm(). Cc: [email protected] Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2703 Signed-off-by: Peter Maydell <[email protected]> Reviewed-by: Richard Henderson <[email protected]> Reviewed-by: Alex Bennée <[email protected]> Tested-by: Alex Bennée <[email protected]> Message-id: [email protected]
1 parent cc503ab commit 02ae315

File tree

1 file changed

+0
-4
lines changed

1 file changed

+0
-4
lines changed

util/qemu-timer.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -409,10 +409,6 @@ static bool timer_mod_ns_locked(QEMUTimerList *timer_list,
409409

410410
static void timerlist_rearm(QEMUTimerList *timer_list)
411411
{
412-
/* Interrupt execution to force deadline recalculation. */
413-
if (icount_enabled() && timer_list->clock->type == QEMU_CLOCK_VIRTUAL) {
414-
icount_start_warp_timer();
415-
}
416412
timerlist_notify(timer_list);
417413
}
418414

0 commit comments

Comments
 (0)