Re: [PATCH v3 15/16] hw/riscv: clint: Avoid using hard-coded timebase frequency

2020-09-01 Thread Philippe Mathieu-Daudé
On 9/1/20 3:39 AM, Bin Meng wrote:
> 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);

As an future improvement, consider using the recently introduced Clock API.

Regards,

Phil.



[PATCH v3 15/16] hw/riscv: clint: Avoid using hard-coded timebase frequency

2020-08-31 Thread Bin Meng
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