aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnup Patel <apatel@ventanamicro.com>2023-01-20 18:29:49 +0530
committerAlistair Francis <alistair.francis@wdc.com>2023-02-07 08:19:23 +1000
commitae0edf2188b3e4346b3e72bb69c75e70869e0c7f (patch)
tree6a075fa46e92ab44aa9bfc1ca4cd6b8ea7194995
parent14cb78bfaf4f99283252d9683ea4c0d97274ddea (diff)
target/riscv: No need to re-start QEMU timer when timecmp == UINT64_MAX
The time CSR will wrap-around immediately after reaching UINT64_MAX so we don't need to re-start QEMU timer when timecmp == UINT64_MAX in riscv_timer_write_timecmp(). Signed-off-by: Anup Patel <apatel@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-Id: <20230120125950.2246378-4-apatel@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
-rw-r--r--target/riscv/time_helper.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
index 4fb2a471a9..b654f91af9 100644
--- a/target/riscv/time_helper.c
+++ b/target/riscv/time_helper.c
@@ -72,6 +72,30 @@ void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer *timer,
riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0));
}
+ /*
+ * Sstc specification says the following about timer interrupt:
+ * "A supervisor timer interrupt becomes pending - as reflected in
+ * the STIP bit in the mip and sip registers - whenever time contains
+ * a value greater than or equal to stimecmp, treating the values
+ * as unsigned integers. Writes to stimecmp are guaranteed to be
+ * reflected in STIP eventually, but not necessarily immediately.
+ * The interrupt remains posted until stimecmp becomes greater
+ * than time - typically as a result of writing stimecmp."
+ *
+ * When timecmp = UINT64_MAX, the time CSR will eventually reach
+ * timecmp value but on next timer tick the time CSR will wrap-around
+ * and become zero which is less than UINT64_MAX. Now, the timer
+ * interrupt behaves like a level triggered interrupt so it will
+ * become 1 when time = timecmp = UINT64_MAX and next timer tick
+ * it will become 0 again because time = 0 < timecmp = UINT64_MAX.
+ *
+ * Based on above, we don't re-start the QEMU timer when timecmp
+ * equals UINT64_MAX.
+ */
+ if (timecmp == UINT64_MAX) {
+ return;
+ }
+
/* otherwise, set up the future timer interrupt */
diff = timecmp - rtc_r;
/* back to ns (note args switched in muldiv64) */