qemu-riscv
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] hw/intc/sifive_clint: Fix expiration time logic


From: s101062801
Subject: [PATCH] hw/intc/sifive_clint: Fix expiration time logic
Date: Sat, 28 Aug 2021 23:46:42 +0800
User-agent: Roundcube Webmail/1.4.2

After timecmp is modified, the value is converted into nanosecond,
and pass to timer_mod.  However, timer_mod perceives the value as
a signed integer.  An example that goes wrong is as follows:

OpenSBI v0.9 initializes the cold boot hart's timecmp to
0xffffffff_ffffffff.  timer_mod then interprets the product of the
following calculation as a negative value.  As a result, the clint
timer is pulled out of timerlist because it looks like it has
expired, which cause the MIP.MTIP is set before any real timer
interrupt.

Signed-off-by: Quey-Liang Kao <s101062801@m101.nthu.edu.tw>
---
 hw/intc/sifive_clint.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/hw/intc/sifive_clint.c b/hw/intc/sifive_clint.c
index 0f41e5ea1c..78f01d17d3 100644
--- a/hw/intc/sifive_clint.c
+++ b/hw/intc/sifive_clint.c
@@ -44,6 +44,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
 {
     uint64_t next;
     uint64_t diff;
+    uint64_t now;

     uint64_t rtc_r = cpu_riscv_read_rtc(timebase_freq);

@@ -59,9 +60,11 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
     riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0));
     diff = cpu->env.timecmp - rtc_r;
     /* back to ns (note args switched in muldiv64) */
-    next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
-        muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
-    timer_mod(cpu->env.timer, next);
+    now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ next = next + muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
+    timer_mod(cpu->env.timer, (next <= now) ?
+                              (int64_t)((1ULL << 63) - 1) :
+                              next);
 }

 /*
--
2.32.0



reply via email to

[Prev in Thread] Current Thread [Next in Thread]