[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 26/33] hw/timer/nrf51_timer: Don't lose time when timer is queried
From: |
Peter Maydell |
Subject: |
[PULL 26/33] hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop |
Date: |
Mon, 19 Jun 2023 15:29:07 +0100 |
The nrf51_timer has a free-running counter which we implement using
the pattern of using two fields (update_counter_ns, counter) to track
the last point at which we calculated the counter value, and the
counter value at that time. Then we can find the current counter
value by converting the difference in wall-clock time between then
and now to a tick count that we need to add to the counter value.
Unfortunately the nrf51_timer's implementation of this has a bug
which means it loses time every time update_counter() is called.
After updating s->counter it always sets s->update_counter_ns to
'now', even though the actual point when s->counter hit the new value
will be some point in the past (half a tick, say). In the worst case
(guest code in a tight loop reading the counter, icount mode) the
counter is continually queried less than a tick after it was last
read, so s->counter never advances but s->update_counter_ns does, and
the guest never makes forward progress.
The fix for this is to only advance update_counter_ns to the
timestamp of the last tick, not all the way to 'now'. (This is the
pattern used in hw/misc/mps2-fpgaio.c's counter.)
Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Joel Stanley <joel@jms.id.au>
Message-id: 20230606134917.3782215-1-peter.maydell@linaro.org
---
hw/timer/nrf51_timer.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c
index 42be79c7363..50c6772383e 100644
--- a/hw/timer/nrf51_timer.c
+++ b/hw/timer/nrf51_timer.c
@@ -45,7 +45,12 @@ static uint32_t update_counter(NRF51TimerState *s, int64_t
now)
uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns);
s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]);
- s->update_counter_ns = now;
+ /*
+ * Only advance the sync time to the timestamp of the last tick,
+ * not all the way to 'now', so we don't lose time if we do
+ * multiple resyncs in a single tick.
+ */
+ s->update_counter_ns += ticks_to_ns(s, ticks);
return ticks;
}
--
2.34.1
- [PULL 23/33] target/arm: Convert load/store tags insns to decodetree, (continued)
- [PULL 23/33] target/arm: Convert load/store tags insns to decodetree, Peter Maydell, 2023/06/19
- [PULL 30/33] hw/arm/raspi: Import Linux raspi definitions as 'raspberrypi-fw-defs.h', Peter Maydell, 2023/06/19
- [PULL 28/33] imx_serial: set wake bit when we receive a data byte, Peter Maydell, 2023/06/19
- [PULL 29/33] docs: sbsa: document board to firmware interface, Peter Maydell, 2023/06/19
- [PULL 33/33] hw/misc/bcm2835_property: Handle CORE_CLK_ID firmware property, Peter Maydell, 2023/06/19
- [PULL 17/33] target/arm: Convert LDR/STR reg+reg to decodetree, Peter Maydell, 2023/06/19
- [PULL 24/33] hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1, Peter Maydell, 2023/06/19
- [PULL 20/33] target/arm: Convert LDAPR/STLR (imm) to decodetree, Peter Maydell, 2023/06/19
- [PULL 21/33] target/arm: Convert load/store (multiple structures) to decodetree, Peter Maydell, 2023/06/19
- [PULL 27/33] hw/arm/Kconfig: sbsa-ref uses Bochs display, Peter Maydell, 2023/06/19
- [PULL 26/33] hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop,
Peter Maydell <=
- [PULL 32/33] hw/misc/bcm2835_property: Replace magic frequency values by definitions, Peter Maydell, 2023/06/19
- Re: [PULL 00/33] target-arm queue, Richard Henderson, 2023/06/19