From 5a65f7b5f4907ca70cb6eae1265e59ccbdfa0937 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 8 Oct 2019 18:17:23 +0100 Subject: [PATCH] hw/timer/arm_timer.c: Switch to transaction-based ptimer API Switch the arm_timer.c code away from bottom-half based ptimers to the new transaction-based ptimer API. This just requires adding begin/commit calls around the various arms of arm_timer_write() that modify the ptimer state, and using the new ptimer_init() function to create the timer. Fixes: https://bugs.launchpad.net/qemu/+bug/1777777 Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20191008171740.9679-5-peter.maydell@linaro.org --- hw/timer/arm_timer.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c index dc33ab310500..af524fabf756 100644 --- a/hw/timer/arm_timer.c +++ b/hw/timer/arm_timer.c @@ -14,7 +14,6 @@ #include "hw/irq.h" #include "hw/ptimer.h" #include "hw/qdev-properties.h" -#include "qemu/main-loop.h" #include "qemu/module.h" #include "qemu/log.h" @@ -75,7 +74,10 @@ static uint32_t arm_timer_read(void *opaque, hwaddr offset) } } -/* Reset the timer limit after settings have changed. */ +/* + * Reset the timer limit after settings have changed. + * May only be called from inside a ptimer transaction block. + */ static void arm_timer_recalibrate(arm_timer_state *s, int reload) { uint32_t limit; @@ -102,13 +104,16 @@ static void arm_timer_write(void *opaque, hwaddr offset, switch (offset >> 2) { case 0: /* TimerLoad */ s->limit = value; + ptimer_transaction_begin(s->timer); arm_timer_recalibrate(s, 1); + ptimer_transaction_commit(s->timer); break; case 1: /* TimerValue */ /* ??? Linux seems to want to write to this readonly register. Ignore it. */ break; case 2: /* TimerControl */ + ptimer_transaction_begin(s->timer); if (s->control & TIMER_CTRL_ENABLE) { /* Pause the timer if it is running. This may cause some inaccuracy dure to rounding, but avoids a whole lot of other @@ -128,13 +133,16 @@ static void arm_timer_write(void *opaque, hwaddr offset, /* Restart the timer if still enabled. */ ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0); } + ptimer_transaction_commit(s->timer); break; case 3: /* TimerIntClr */ s->int_level = 0; break; case 6: /* TimerBGLoad */ s->limit = value; + ptimer_transaction_begin(s->timer); arm_timer_recalibrate(s, 0); + ptimer_transaction_commit(s->timer); break; default: qemu_log_mask(LOG_GUEST_ERROR, @@ -166,14 +174,12 @@ static const VMStateDescription vmstate_arm_timer = { static arm_timer_state *arm_timer_init(uint32_t freq) { arm_timer_state *s; - QEMUBH *bh; s = (arm_timer_state *)g_malloc0(sizeof(arm_timer_state)); s->freq = freq; s->control = TIMER_CTRL_IE; - bh = qemu_bh_new(arm_timer_tick, s); - s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT); + s->timer = ptimer_init(arm_timer_tick, s, PTIMER_POLICY_DEFAULT); vmstate_register(NULL, -1, &vmstate_arm_timer, s); return s; }