From: Bin Meng
At present the CLINT timestamp is using a hard-coded timebase
frequency value SIFIVE_CLINT_TIMEBASE_FREQ. This might not be
true for all boards.
Add a new 'timebase-freq' property to the CLINT device, and
update various functions to accept this as a parameter.
Signed-off-by: Bin Meng
Reviewed-by: Alistair Francis
---
(no changes since v1)
include/hw/riscv/sifive_clint.h | 4 +++-
target/riscv/cpu.h | 6 --
hw/riscv/microchip_pfsoc.c | 6 +-
hw/riscv/sifive_clint.c | 26 +++---
hw/riscv/sifive_e.c | 3 ++-
hw/riscv/sifive_u.c | 3 ++-
hw/riscv/spike.c| 3 ++-
hw/riscv/virt.c | 3 ++-
target/riscv/cpu_helper.c | 4 +++-
target/riscv/csr.c | 4 ++--
10 files changed, 40 insertions(+), 22 deletions(-)
diff --git a/include/hw/riscv/sifive_clint.h b/include/hw/riscv/sifive_clint.h
index 9f5fb3d..a30be0f 100644
--- a/include/hw/riscv/sifive_clint.h
+++ b/include/hw/riscv/sifive_clint.h
@@ -39,11 +39,13 @@ typedef struct SiFiveCLINTState {
uint32_t timecmp_base;
uint32_t time_base;
uint32_t aperture_size;
+uint32_t timebase_freq;
} SiFiveCLINTState;
DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base,
-uint32_t timecmp_base, uint32_t time_base, bool provide_rdtime);
+uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
+bool provide_rdtime);
enum {
SIFIVE_SIP_BASE = 0x0,
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index dc350f0..a003d83 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -219,7 +219,8 @@ struct CPURISCVState {
pmp_table_t pmp_state;
/* machine specific rdtime callback */
-uint64_t (*rdtime_fn)(void);
+uint64_t (*rdtime_fn)(uint32_t);
+uint32_t rdtime_fn_arg;
/* True if in debugger mode. */
bool debugger;
@@ -349,7 +350,8 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env);
int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts);
uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value);
#define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
-void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void));
+void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t),
+ uint32_t arg);
#endif
void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index 11ebdd1..da6bd29 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -60,6 +60,9 @@
#define BIOS_FILENAME "hss.bin"
#define RESET_VECTOR0x2022
+/* CLINT timebase frequency */
+#define CLINT_TIMEBASE_FREQ 100
+
/* GEM version */
#define GEM_REVISION0x0107010c
@@ -187,7 +190,8 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev,
Error **errp)
/* CLINT */
sifive_clint_create(memmap[MICROCHIP_PFSOC_CLINT].base,
memmap[MICROCHIP_PFSOC_CLINT].size, 0, ms->smp.cpus,
-SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false);
+SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
+CLINT_TIMEBASE_FREQ, false);
/* L2 cache controller */
create_unimplemented_device("microchip.pfsoc.l2cc",
diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
index 15e13d5..fa1ddf2 100644
--- a/hw/riscv/sifive_clint.c
+++ b/hw/riscv/sifive_clint.c
@@ -29,22 +29,23 @@
#include "hw/riscv/sifive_clint.h"
#include "qemu/timer.h"
-static uint64_t cpu_riscv_read_rtc(void)
+static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
{
return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
-SIFIVE_CLINT_TIMEBASE_FREQ, NANOSECONDS_PER_SECOND);
+timebase_freq, NANOSECONDS_PER_SECOND);
}
/*
* Called when timecmp is written to update the QEMU timer or immediately
* trigger timer interrupt if mtimecmp <= current timer value.
*/
-static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value)
+static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
+ uint32_t timebase_freq)
{
uint64_t next;
uint64_t diff;
-uint64_t rtc_r = cpu_riscv_read_rtc();
+uint64_t rtc_r = cpu_riscv_read_rtc(timebase_freq);
cpu->env.timecmp = value;
if (cpu->env.timecmp <= rtc_r) {
@@ -59,7 +60,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu,
uint64_t value)
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, SIFIVE_CLINT_TIMEBASE_FREQ);
+muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
timer_mod(cpu->env.timer, next);
}
@@ -112,10 +113,10 @@ static uint64_t