From: Peter Maydell <peter.maydell@linaro.org>
To: Joel Stanley <joel@jms.id.au>
Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org, qemu-stable@nongnu.org
Subject: Re: [PATCH] hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop
Date: Wed, 7 Jun 2023 14:03:04 +0100 [thread overview]
Message-ID: <CAFEAcA812y_cG2+AMPRwAE_8_9DGOM_J7_zqHFju5mazr9hqYQ@mail.gmail.com> (raw)
In-Reply-To: <CACPK8Xd3_ets6btF9ULqjFn_eT55M8t8C+_iQXg-_eXGDLDWqw@mail.gmail.com>
On Wed, 7 Jun 2023 at 12:26, Joel Stanley <joel@jms.id.au> wrote:
>
> On Tue, 6 Jun 2023 at 13:49, Peter Maydell <peter.maydell@linaro.org> wrote:
> >
> > 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>
> > ---
> > The hang in icount mode was discovered by the Zephyr folks as part
> > of their investigation into
> > https://github.com/zephyrproject-rtos/zephyr/issues/57512
>
> Did you get an image to test with?
Yes, somewhere in the comments on one of the pullrequests
associated with that issue one of the Zephyr devs helpfully
provided a test image.
> Reviewed-by: Joel Stanley <joel@jms.id.au>
>
> >
> > 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;
>
> We're still returning the number of ticks up to 'now'. Should we
> instead return the elapsed ticks? If not, we will expire the timer
> early.
Hmm, I'm not sure what you mean here. The tick count at the
'update_counter_ns' time and the tick count at 'now' should be
identical (because there can't ever be an entire tick difference
between them).
thanks
-- PMM
prev parent reply other threads:[~2023-06-07 13:03 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-06 13:49 [PATCH] hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop Peter Maydell
2023-06-07 11:26 ` Joel Stanley
2023-06-07 13:03 ` Peter Maydell [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAFEAcA812y_cG2+AMPRwAE_8_9DGOM_J7_zqHFju5mazr9hqYQ@mail.gmail.com \
--to=peter.maydell@linaro.org \
--cc=joel@jms.id.au \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=qemu-stable@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).