qemu-devel
[Top][All Lists]
Advanced

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

Re: [PATCH 17/18] hw/riscv: clint: Avoid using hard-coded timebase frequ


From: Alistair Francis
Subject: Re: [PATCH 17/18] hw/riscv: clint: Avoid using hard-coded timebase frequency
Date: Tue, 25 Aug 2020 11:33:59 -0700

On Fri, Aug 14, 2020 at 9:54 AM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> From: Bin Meng <bin.meng@windriver.com>
>
> 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 <bin.meng@windriver.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>
>  hw/riscv/microchip_pfsoc.c      |  6 +++++-
>  hw/riscv/sifive_clint.c         | 25 ++++++++++++++-----------
>  hw/riscv/sifive_e.c             |  3 ++-
>  hw/riscv/sifive_u.c             |  3 ++-
>  hw/riscv/spike.c                |  2 +-
>  hw/riscv/virt.c                 |  3 ++-
>  include/hw/riscv/sifive_clint.h |  3 ++-
>  target/riscv/cpu.h              |  6 ++++--
>  target/riscv/cpu_helper.c       |  4 +++-
>  target/riscv/csr.c              |  4 ++--
>  10 files changed, 37 insertions(+), 22 deletions(-)
>
> diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
> index 139284a..e8b7f86 100644
> --- a/hw/riscv/microchip_pfsoc.c
> +++ b/hw/riscv/microchip_pfsoc.c
> @@ -60,6 +60,9 @@
>  #define BIOS_FILENAME   "hss.bin"
>  #define RESET_VECTOR    0x20220000
>
> +/* CLINT timebase frequency */
> +#define CLINT_TIMEBASE_FREQ 1000000
> +
>  /* GEM version */
>  #define GEM_REVISION    0x0107010c
>
> @@ -189,7 +192,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, 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 669c21a..a568568 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);
>  }
>
> @@ -111,10 +112,10 @@ static uint64_t sifive_clint_read(void *opaque, hwaddr 
> addr, unsigned size)
>          }
>      } else if (addr == clint->time_base) {
>          /* time_lo */
> -        return cpu_riscv_read_rtc() & 0xFFFFFFFF;
> +        return cpu_riscv_read_rtc(clint->timebase_freq) & 0xFFFFFFFF;
>      } else if (addr == clint->time_base + 4) {
>          /* time_hi */
> -        return (cpu_riscv_read_rtc() >> 32) & 0xFFFFFFFF;
> +        return (cpu_riscv_read_rtc(clint->timebase_freq) >> 32) & 0xFFFFFFFF;
>      }
>
>      error_report("clint: invalid read: %08x", (uint32_t)addr);
> @@ -151,13 +152,13 @@ static void sifive_clint_write(void *opaque, hwaddr 
> addr, uint64_t value,
>              /* timecmp_lo */
>              uint64_t timecmp_hi = env->timecmp >> 32;
>              sifive_clint_write_timecmp(RISCV_CPU(cpu),
> -                timecmp_hi << 32 | (value & 0xFFFFFFFF));
> +                timecmp_hi << 32 | (value & 0xFFFFFFFF), 
> clint->timebase_freq);
>              return;
>          } else if ((addr & 0x7) == 4) {
>              /* timecmp_hi */
>              uint64_t timecmp_lo = env->timecmp;
>              sifive_clint_write_timecmp(RISCV_CPU(cpu),
> -                value << 32 | (timecmp_lo & 0xFFFFFFFF));
> +                value << 32 | (timecmp_lo & 0xFFFFFFFF), 
> clint->timebase_freq);
>          } else {
>              error_report("clint: invalid timecmp write: %08x", 
> (uint32_t)addr);
>          }
> @@ -191,6 +192,7 @@ static Property sifive_clint_properties[] = {
>      DEFINE_PROP_UINT32("timecmp-base", SiFiveCLINTState, timecmp_base, 0),
>      DEFINE_PROP_UINT32("time-base", SiFiveCLINTState, time_base, 0),
>      DEFINE_PROP_UINT32("aperture-size", SiFiveCLINTState, aperture_size, 0),
> +    DEFINE_PROP_UINT32("timebase-freq", SiFiveCLINTState, timebase_freq, 0),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>
> @@ -229,7 +231,7 @@ type_init(sifive_clint_register_types)
>   */
>  DeviceState *sifive_clint_create(hwaddr addr, hwaddr size, uint32_t 
> num_harts,
>      uint32_t sip_base, uint32_t timecmp_base, uint32_t time_base,
> -    bool provide_rdtime)
> +    uint32_t timebase_freq, bool provide_rdtime)
>  {
>      int i;
>      for (i = 0; i < num_harts; i++) {
> @@ -239,7 +241,7 @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr 
> size, uint32_t num_harts,
>              continue;
>          }
>          if (provide_rdtime) {
> -            riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc);
> +            riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, timebase_freq);
>          }
>          env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
>                                    &sifive_clint_timer_cb, cpu);
> @@ -252,6 +254,7 @@ DeviceState *sifive_clint_create(hwaddr addr, hwaddr 
> size, uint32_t num_harts,
>      qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base);
>      qdev_prop_set_uint32(dev, "time-base", time_base);
>      qdev_prop_set_uint32(dev, "aperture-size", size);
> +    qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq);
>      sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>      sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
>      return dev;
> diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
> index c84d407..e7f6460 100644
> --- a/hw/riscv/sifive_e.c
> +++ b/hw/riscv/sifive_e.c
> @@ -213,7 +213,8 @@ static void sifive_e_soc_realize(DeviceState *dev, Error 
> **errp)
>          memmap[SIFIVE_E_PLIC].size);
>      sifive_clint_create(memmap[SIFIVE_E_CLINT].base,
>          memmap[SIFIVE_E_CLINT].size, ms->smp.cpus,
> -        SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false);
> +        SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
> +        SIFIVE_CLINT_TIMEBASE_FREQ, false);
>      create_unimplemented_device("riscv.sifive.e.aon",
>          memmap[SIFIVE_E_AON].base, memmap[SIFIVE_E_AON].size);
>      sifive_e_prci_create(memmap[SIFIVE_E_PRCI].base);
> diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> index e256da2..5ec9fca 100644
> --- a/hw/riscv/sifive_u.c
> +++ b/hw/riscv/sifive_u.c
> @@ -706,7 +706,8 @@ static void sifive_u_soc_realize(DeviceState *dev, Error 
> **errp)
>          serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART1_IRQ));
>      sifive_clint_create(memmap[SIFIVE_U_CLINT].base,
>          memmap[SIFIVE_U_CLINT].size, ms->smp.cpus,
> -        SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, false);
> +        SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
> +        SIFIVE_CLINT_TIMEBASE_FREQ, false);
>
>      if (!sysbus_realize(SYS_BUS_DEVICE(&s->prci), errp)) {
>          return;
> diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
> index 13958bd..ae8593a 100644
> --- a/hw/riscv/spike.c
> +++ b/hw/riscv/spike.c
> @@ -235,7 +235,7 @@ static void spike_board_init(MachineState *machine)
>      /* Core Local Interruptor (timer and IPI) */
>      sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size,
>          smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
> -        false);
> +        SIFIVE_CLINT_TIMEBASE_FREQ, false);
>  }
>
>  static void spike_machine_init(MachineClass *mc)
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 6e91cf1..af0d06a 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -572,7 +572,8 @@ static void virt_machine_init(MachineState *machine)
>          memmap[VIRT_PLIC].size);
>      sifive_clint_create(memmap[VIRT_CLINT].base,
>          memmap[VIRT_CLINT].size, smp_cpus,
> -        SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE, true);
> +        SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
> +        SIFIVE_CLINT_TIMEBASE_FREQ, true);
>      sifive_test_create(memmap[VIRT_TEST].base);
>
>      for (i = 0; i < VIRTIO_COUNT; i++) {
> diff --git a/include/hw/riscv/sifive_clint.h b/include/hw/riscv/sifive_clint.h
> index 4a720bf..eb8577a 100644
> --- a/include/hw/riscv/sifive_clint.h
> +++ b/include/hw/riscv/sifive_clint.h
> @@ -38,11 +38,12 @@ 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 
> num_harts,
>      uint32_t sip_base, uint32_t timecmp_base, uint32_t time_base,
> -    bool provide_rdtime);
> +    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 d34bcfa..02486c3 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;
> @@ -347,7 +348,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/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index fd1d373..c82a521 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -258,9 +258,11 @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t 
> mask, uint32_t value)
>      return old;
>  }
>
> -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)
>  {
>      env->rdtime_fn = fn;
> +    env->rdtime_fn_arg = arg;
>  }
>
>  void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 6a96a01..6cef1ac 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -294,7 +294,7 @@ static int read_time(CPURISCVState *env, int csrno, 
> target_ulong *val)
>          return -1;
>      }
>
> -    *val = env->rdtime_fn() + delta;
> +    *val = env->rdtime_fn(env->rdtime_fn_arg) + delta;
>      return 0;
>  }
>
> @@ -307,7 +307,7 @@ static int read_timeh(CPURISCVState *env, int csrno, 
> target_ulong *val)
>          return -1;
>      }
>
> -    *val = (env->rdtime_fn() + delta) >> 32;
> +    *val = (env->rdtime_fn(env->rdtime_fn_arg) + delta) >> 32;
>      return 0;
>  }
>  #endif
> --
> 2.7.4
>
>



reply via email to

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