From: Stafford Horne <shorne@gmail.com>
To: Joel Holdsworth <jholdsworth@nvidia.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [PATCH] hw/openrisc: Fixed undercounting of TTCR in continuous mode
Date: Wed, 13 Nov 2024 07:00:35 +0000 [thread overview]
Message-ID: <ZzROk0C5GOJZCqpA@antec> (raw)
In-Reply-To: <20240607222933.45791-1-jholdsworth@nvidia.com>
On Fri, Jun 07, 2024 at 03:29:33PM -0700, Joel Holdsworth via wrote:
> In the existing design, TTCR is prone to undercounting when running in
> continuous mode. This manifests as a timer interrupt appearing to
> trigger a few cycles prior to the deadline set in SPR_TTMR_TP.
>
> When the timer triggers, the virtual time delta in nanoseconds between
> the time when the timer was set, and when it triggers is calculated.
> This nanoseconds value is then divided by TIMER_PERIOD (50) to compute
> an increment of cycles to apply to TTCR.
>
> However, this calculation rounds down the number of cycles causing the
> undercounting.
>
> A simplistic solution would be to instead round up the number of cycles,
> however this will result in the accumulation of timing error over time.
>
> This patch corrects the issue by calculating the time delta in
> nanoseconds between when the timer was last reset and the timer event.
> This approach allows the TTCR value to be rounded up, but without
> accumulating error over time.
>
> Signed-off-by: Joel Holdsworth <jholdsworth@nvidia.com>
> ---
> hw/openrisc/cputimer.c | 22 +++++++++++++---------
> 1 file changed, 13 insertions(+), 9 deletions(-)
>
> diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
> index 835986c4db..ddc129aa48 100644
> --- a/hw/openrisc/cputimer.c
> +++ b/hw/openrisc/cputimer.c
> @@ -29,7 +29,8 @@
> /* Tick Timer global state to allow all cores to be in sync */
> typedef struct OR1KTimerState {
> uint32_t ttcr;
> - uint64_t last_clk;
> + uint32_t ttcr_offset;
> + uint64_t clk_offset;
> } OR1KTimerState;
>
> static OR1KTimerState *or1k_timer;
> @@ -37,6 +38,8 @@ static OR1KTimerState *or1k_timer;
> void cpu_openrisc_count_set(OpenRISCCPU *cpu, uint32_t val)
> {
> or1k_timer->ttcr = val;
> + or1k_timer->ttcr_offset = val;
> + or1k_timer->clk_offset = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> }
>
> uint32_t cpu_openrisc_count_get(OpenRISCCPU *cpu)
> @@ -53,9 +56,8 @@ void cpu_openrisc_count_update(OpenRISCCPU *cpu)
> return;
> }
> now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> - or1k_timer->ttcr += (uint32_t)((now - or1k_timer->last_clk)
> - / TIMER_PERIOD);
> - or1k_timer->last_clk = now;
> + or1k_timer->ttcr = (now - or1k_timer->clk_offset + TIMER_PERIOD - 1) / TIMER_PERIOD +
> + or1k_timer->ttcr_offset;
> }
>
> /* Update the next timeout time as difference between ttmr and ttcr */
> @@ -69,7 +71,7 @@ void cpu_openrisc_timer_update(OpenRISCCPU *cpu)
> }
>
> cpu_openrisc_count_update(cpu);
> - now = or1k_timer->last_clk;
> + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
>
> if ((cpu->env.ttmr & TTMR_TP) <= (or1k_timer->ttcr & TTMR_TP)) {
> wait = TTMR_TP - (or1k_timer->ttcr & TTMR_TP) + 1;
> @@ -110,7 +112,8 @@ static void openrisc_timer_cb(void *opaque)
> case TIMER_NONE:
> break;
> case TIMER_INTR:
> - or1k_timer->ttcr = 0;
> + /* Zero the count by applying a negative offset to the counter */
> + or1k_timer->ttcr_offset += UINT32_MAX - (cpu->env.ttmr & TTMR_TP);
Hi Joel,
I am trying to get this merged as I am finally getting some time for this again
after a long project at work.
Why here do you do += UINT32_MAX - (cpu->env.ttmr & TTMR_TP)?
Is there an edge case I am not thinking of that is making you use UINT32_MAX?
Wouldn't this be the same as
r1k_timer->ttcr_offset -= 1 - (cpu->env.ttmr & TTMR_TP);
-Stafford
prev parent reply other threads:[~2024-11-13 7:00 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-07 22:29 [PATCH] hw/openrisc: Fixed undercounting of TTCR in continuous mode Joel Holdsworth via
2024-06-08 22:30 ` Stafford Horne
2024-06-10 19:29 ` Joel Holdsworth
2024-08-05 6:12 ` Stafford Horne
2024-11-13 7:00 ` Stafford Horne [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=ZzROk0C5GOJZCqpA@antec \
--to=shorne@gmail.com \
--cc=jholdsworth@nvidia.com \
--cc=qemu-devel@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.