mirror of https://github.com/xemu-project/xemu.git
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 <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20191008171740.9679-5-peter.maydell@linaro.org
This commit is contained in:
parent
91b37aea0e
commit
5a65f7b5f4
|
@ -14,7 +14,6 @@
|
||||||
#include "hw/irq.h"
|
#include "hw/irq.h"
|
||||||
#include "hw/ptimer.h"
|
#include "hw/ptimer.h"
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
#include "qemu/main-loop.h"
|
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "qemu/log.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)
|
static void arm_timer_recalibrate(arm_timer_state *s, int reload)
|
||||||
{
|
{
|
||||||
uint32_t limit;
|
uint32_t limit;
|
||||||
|
@ -102,13 +104,16 @@ static void arm_timer_write(void *opaque, hwaddr offset,
|
||||||
switch (offset >> 2) {
|
switch (offset >> 2) {
|
||||||
case 0: /* TimerLoad */
|
case 0: /* TimerLoad */
|
||||||
s->limit = value;
|
s->limit = value;
|
||||||
|
ptimer_transaction_begin(s->timer);
|
||||||
arm_timer_recalibrate(s, 1);
|
arm_timer_recalibrate(s, 1);
|
||||||
|
ptimer_transaction_commit(s->timer);
|
||||||
break;
|
break;
|
||||||
case 1: /* TimerValue */
|
case 1: /* TimerValue */
|
||||||
/* ??? Linux seems to want to write to this readonly register.
|
/* ??? Linux seems to want to write to this readonly register.
|
||||||
Ignore it. */
|
Ignore it. */
|
||||||
break;
|
break;
|
||||||
case 2: /* TimerControl */
|
case 2: /* TimerControl */
|
||||||
|
ptimer_transaction_begin(s->timer);
|
||||||
if (s->control & TIMER_CTRL_ENABLE) {
|
if (s->control & TIMER_CTRL_ENABLE) {
|
||||||
/* Pause the timer if it is running. This may cause some
|
/* Pause the timer if it is running. This may cause some
|
||||||
inaccuracy dure to rounding, but avoids a whole lot of other
|
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. */
|
/* Restart the timer if still enabled. */
|
||||||
ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0);
|
ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0);
|
||||||
}
|
}
|
||||||
|
ptimer_transaction_commit(s->timer);
|
||||||
break;
|
break;
|
||||||
case 3: /* TimerIntClr */
|
case 3: /* TimerIntClr */
|
||||||
s->int_level = 0;
|
s->int_level = 0;
|
||||||
break;
|
break;
|
||||||
case 6: /* TimerBGLoad */
|
case 6: /* TimerBGLoad */
|
||||||
s->limit = value;
|
s->limit = value;
|
||||||
|
ptimer_transaction_begin(s->timer);
|
||||||
arm_timer_recalibrate(s, 0);
|
arm_timer_recalibrate(s, 0);
|
||||||
|
ptimer_transaction_commit(s->timer);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
qemu_log_mask(LOG_GUEST_ERROR,
|
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)
|
static arm_timer_state *arm_timer_init(uint32_t freq)
|
||||||
{
|
{
|
||||||
arm_timer_state *s;
|
arm_timer_state *s;
|
||||||
QEMUBH *bh;
|
|
||||||
|
|
||||||
s = (arm_timer_state *)g_malloc0(sizeof(arm_timer_state));
|
s = (arm_timer_state *)g_malloc0(sizeof(arm_timer_state));
|
||||||
s->freq = freq;
|
s->freq = freq;
|
||||||
s->control = TIMER_CTRL_IE;
|
s->control = TIMER_CTRL_IE;
|
||||||
|
|
||||||
bh = qemu_bh_new(arm_timer_tick, s);
|
s->timer = ptimer_init(arm_timer_tick, s, PTIMER_POLICY_DEFAULT);
|
||||||
s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
|
|
||||||
vmstate_register(NULL, -1, &vmstate_arm_timer, s);
|
vmstate_register(NULL, -1, &vmstate_arm_timer, s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue