[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
- [PATCH] hw/intc/sifive_clint: Fix expiration time logic,
s101062801 <=