[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 01/13] hw/openrisc: Fixed undercounting of TTCR in continuous mode
From: |
Philippe Mathieu-Daudé |
Subject: |
[PULL 01/13] hw/openrisc: Fixed undercounting of TTCR in continuous mode |
Date: |
Tue, 3 Dec 2024 12:31:28 +0100 |
From: Joel Holdsworth <jholdsworth@nvidia.com>
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>
[stafford: Incremented version in vmstate_or1k_timer, checkpatch fixes]
Signed-off-by: Stafford Horne <shorne@gmail.com>
Message-ID: <20241203110536.402131-3-shorne@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
hw/openrisc/cputimer.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
index 835986c4dbe..87aa3533237 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 = or1k_timer->ttcr_offset +
+ DIV_ROUND_UP(now - or1k_timer->clk_offset, TIMER_PERIOD);
}
/* 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 -= (cpu->env.ttmr & TTMR_TP);
break;
case TIMER_SHOT:
cpu_openrisc_count_stop(cpu);
@@ -137,17 +140,18 @@ static void openrisc_count_reset(void *opaque)
/* Reset the global timer state. */
static void openrisc_timer_reset(void *opaque)
{
- or1k_timer->ttcr = 0x00000000;
- or1k_timer->last_clk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ OpenRISCCPU *cpu = opaque;
+ cpu_openrisc_count_set(cpu, 0);
}
static const VMStateDescription vmstate_or1k_timer = {
.name = "or1k_timer",
- .version_id = 1,
- .minimum_version_id = 1,
+ .version_id = 2,
+ .minimum_version_id = 2,
.fields = (const VMStateField[]) {
VMSTATE_UINT32(ttcr, OR1KTimerState),
- VMSTATE_UINT64(last_clk, OR1KTimerState),
+ VMSTATE_UINT32(ttcr_offset, OR1KTimerState),
+ VMSTATE_UINT64(clk_offset, OR1KTimerState),
VMSTATE_END_OF_LIST()
}
};
--
2.45.2
- [PULL 00/13] Misc fixes for 2024-12-03, Philippe Mathieu-Daudé, 2024/12/03
- [PULL 01/13] hw/openrisc: Fixed undercounting of TTCR in continuous mode,
Philippe Mathieu-Daudé <=
- [PULL 02/13] hw/openrisc/openrisc_sim: keep serial@90000000 as default, Philippe Mathieu-Daudé, 2024/12/03
- [PULL 03/13] ui/cocoa: Temporarily ignore annoying deprecated declaration warnings, Philippe Mathieu-Daudé, 2024/12/03
- [PULL 04/13] MAINTAINERS: add myself as the maintainer for LoongArch VirtMachine, Philippe Mathieu-Daudé, 2024/12/03
- [PULL 05/13] meson: Add missing SDL dependency to system/main.c, Philippe Mathieu-Daudé, 2024/12/03
- [PULL 06/13] MAINTAINERS: update email addr for Brian Cain, Philippe Mathieu-Daudé, 2024/12/03
- [PULL 07/13] hw/core/machine: diagnose wrapping of maxmem, Philippe Mathieu-Daudé, 2024/12/03
- [PULL 08/13] target/riscv: Avoid bad shift in riscv_cpu_do_interrupt(), Philippe Mathieu-Daudé, 2024/12/03
- [PULL 09/13] hw/display/vga: Do not reset 'big_endian_fb' in vga_common_reset(), Philippe Mathieu-Daudé, 2024/12/03
- [PULL 10/13] hw/virtio: fix crash in processing balloon stats, Philippe Mathieu-Daudé, 2024/12/03