Re: [PATCH v8 07/12] target/riscv: Support mcycle/minstret write operation

2022-05-18 Thread Atish Patra
On Sat, May 14, 2022 at 12:46 AM Frank Chang  wrote:
>
> On Fri, May 13, 2022 at 11:58 PM Atish Kumar Patra  
> wrote:
>>
>> On Thu, May 12, 2022 at 11:29 PM Frank Chang  wrote:
>> >
>> > On Thu, May 12, 2022 at 6:01 AM Atish Patra  wrote:
>> >>
>> >> From: Atish Patra 
>> >>
>> >> mcycle/minstret are actually WARL registers and can be written with any
>> >> given value. With SBI PMU extension, it will be used to store a initial
>> >> value provided from supervisor OS. The Qemu also need prohibit the counter
>> >> increment if mcountinhibit is set.
>> >>
>> >> Support mcycle/minstret through generic counter infrastructure.
>> >>
>> >> Reviewed-by: Alistair Francis 
>> >> Signed-off-by: Atish Patra 
>> >> Signed-off-by: Atish Patra 
>> >> ---
>> >>  target/riscv/cpu.h   |  23 --
>> >>  target/riscv/csr.c   | 157 ---
>> >>  target/riscv/machine.c   |  25 ++-
>> >>  target/riscv/meson.build |   3 +-
>> >>  target/riscv/pmu.c   |  32 
>> >>  target/riscv/pmu.h   |  28 +++
>> >>  6 files changed, 214 insertions(+), 54 deletions(-)
>> >>  create mode 100644 target/riscv/pmu.c
>> >>  create mode 100644 target/riscv/pmu.h
>> >>
>> >> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
>> >> index 32cdd9070be5..f60072e0fd3d 100644
>> >> --- a/target/riscv/cpu.h
>> >> +++ b/target/riscv/cpu.h
>> >> @@ -111,7 +111,7 @@ typedef struct CPUArchState CPURISCVState;
>> >>  #endif
>> >>
>> >>  #define RV_VLEN_MAX 1024
>> >> -#define RV_MAX_MHPMEVENTS 29
>> >> +#define RV_MAX_MHPMEVENTS 32
>> >>  #define RV_MAX_MHPMCOUNTERS 32
>> >>
>> >>  FIELD(VTYPE, VLMUL, 0, 3)
>> >> @@ -121,6 +121,18 @@ FIELD(VTYPE, VMA, 7, 1)
>> >>  FIELD(VTYPE, VEDIV, 8, 2)
>> >>  FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11)
>> >>
>> >> +typedef struct PMUCTRState {
>> >> +/* Current value of a counter */
>> >> +target_ulong mhpmcounter_val;
>> >> +/* Current value of a counter in RV32*/
>> >> +target_ulong mhpmcounterh_val;
>> >> +/* Snapshot values of counter */
>> >> +target_ulong mhpmcounter_prev;
>> >> +/* Snapshort value of a counter in RV32 */
>> >> +target_ulong mhpmcounterh_prev;
>> >> +bool started;
>> >> +} PMUCTRState;
>> >> +
>> >>  struct CPUArchState {
>> >>  target_ulong gpr[32];
>> >>  target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
>> >> @@ -273,13 +285,10 @@ struct CPUArchState {
>> >>
>> >>  target_ulong mcountinhibit;
>> >>
>> >> -/* PMU counter configured values */
>> >> -target_ulong mhpmcounter_val[RV_MAX_MHPMCOUNTERS];
>> >> -
>> >> -/* for RV32 */
>> >> -target_ulong mhpmcounterh_val[RV_MAX_MHPMCOUNTERS];
>> >> +/* PMU counter state */
>> >> +PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
>> >>
>> >> -/* PMU event selector configured values */
>> >> +/* PMU event selector configured values. First three are unused*/
>> >>  target_ulong mhpmevent_val[RV_MAX_MHPMEVENTS];
>> >>
>> >>  target_ulong sscratch;
>> >> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
>> >> index 87aa601e5ddb..c050ed2e2c1b 100644
>> >> --- a/target/riscv/csr.c
>> >> +++ b/target/riscv/csr.c
>> >> @@ -21,6 +21,7 @@
>> >>  #include "qemu/log.h"
>> >>  #include "qemu/timer.h"
>> >>  #include "cpu.h"
>> >> +#include "pmu.h"
>> >>  #include "qemu/main-loop.h"
>> >>  #include "exec/exec-all.h"
>> >>  #include "sysemu/cpu-timers.h"
>> >> @@ -597,34 +598,28 @@ static int write_vcsr(CPURISCVState *env, int 
>> >> csrno, target_ulong val)
>> >>  }
>> >>
>> >>  /* User Timers and Counters */
>> >> -static RISCVException read_instret(CPURISCVState *env, int csrno,
>> >> -   target_ulong *val)
>> >> +static target_ulong get_ticks(bool shift)
>> >>  {
>> >> +int64_t val;
>> >> +target_ulong result;
>> >> +
>> >>  #if !defined(CONFIG_USER_ONLY)
>> >>  if (icount_enabled()) {
>> >> -*val = icount_get();
>> >> +val = icount_get();
>> >>  } else {
>> >> -*val = cpu_get_host_ticks();
>> >> +val = cpu_get_host_ticks();
>> >>  }
>> >>  #else
>> >> -*val = cpu_get_host_ticks();
>> >> +val = cpu_get_host_ticks();
>> >>  #endif
>> >> -return RISCV_EXCP_NONE;
>> >> -}
>> >>
>> >> -static RISCVException read_instreth(CPURISCVState *env, int csrno,
>> >> -target_ulong *val)
>> >> -{
>> >> -#if !defined(CONFIG_USER_ONLY)
>> >> -if (icount_enabled()) {
>> >> -*val = icount_get() >> 32;
>> >> +if (shift) {
>> >> +result = val >> 32;
>> >>  } else {
>> >> -*val = cpu_get_host_ticks() >> 32;
>> >> +result = val;
>> >>  }
>> >> -#else
>> >> -*val = cpu_get_host_ticks() >> 32;
>> >> -#endif
>> >> -return RISCV_EXCP_NONE;
>> >> +
>> >> +return result;
>> >>  }
>> >>
>> >>  #if defined(CONFIG_USER_ONLY)
>> >> @@ -642,11 +637,23 @@ static RISCVException read_timeh(CPURISCVState 
>> >> *env, int csrno,
>> >> 

Re: [PATCH v8 07/12] target/riscv: Support mcycle/minstret write operation

2022-05-14 Thread Frank Chang
On Fri, May 13, 2022 at 11:58 PM Atish Kumar Patra 
wrote:

> On Thu, May 12, 2022 at 11:29 PM Frank Chang 
> wrote:
> >
> > On Thu, May 12, 2022 at 6:01 AM Atish Patra  wrote:
> >>
> >> From: Atish Patra 
> >>
> >> mcycle/minstret are actually WARL registers and can be written with any
> >> given value. With SBI PMU extension, it will be used to store a initial
> >> value provided from supervisor OS. The Qemu also need prohibit the
> counter
> >> increment if mcountinhibit is set.
> >>
> >> Support mcycle/minstret through generic counter infrastructure.
> >>
> >> Reviewed-by: Alistair Francis 
> >> Signed-off-by: Atish Patra 
> >> Signed-off-by: Atish Patra 
> >> ---
> >>  target/riscv/cpu.h   |  23 --
> >>  target/riscv/csr.c   | 157 ---
> >>  target/riscv/machine.c   |  25 ++-
> >>  target/riscv/meson.build |   3 +-
> >>  target/riscv/pmu.c   |  32 
> >>  target/riscv/pmu.h   |  28 +++
> >>  6 files changed, 214 insertions(+), 54 deletions(-)
> >>  create mode 100644 target/riscv/pmu.c
> >>  create mode 100644 target/riscv/pmu.h
> >>
> >> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> >> index 32cdd9070be5..f60072e0fd3d 100644
> >> --- a/target/riscv/cpu.h
> >> +++ b/target/riscv/cpu.h
> >> @@ -111,7 +111,7 @@ typedef struct CPUArchState CPURISCVState;
> >>  #endif
> >>
> >>  #define RV_VLEN_MAX 1024
> >> -#define RV_MAX_MHPMEVENTS 29
> >> +#define RV_MAX_MHPMEVENTS 32
> >>  #define RV_MAX_MHPMCOUNTERS 32
> >>
> >>  FIELD(VTYPE, VLMUL, 0, 3)
> >> @@ -121,6 +121,18 @@ FIELD(VTYPE, VMA, 7, 1)
> >>  FIELD(VTYPE, VEDIV, 8, 2)
> >>  FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11)
> >>
> >> +typedef struct PMUCTRState {
> >> +/* Current value of a counter */
> >> +target_ulong mhpmcounter_val;
> >> +/* Current value of a counter in RV32*/
> >> +target_ulong mhpmcounterh_val;
> >> +/* Snapshot values of counter */
> >> +target_ulong mhpmcounter_prev;
> >> +/* Snapshort value of a counter in RV32 */
> >> +target_ulong mhpmcounterh_prev;
> >> +bool started;
> >> +} PMUCTRState;
> >> +
> >>  struct CPUArchState {
> >>  target_ulong gpr[32];
> >>  target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
> >> @@ -273,13 +285,10 @@ struct CPUArchState {
> >>
> >>  target_ulong mcountinhibit;
> >>
> >> -/* PMU counter configured values */
> >> -target_ulong mhpmcounter_val[RV_MAX_MHPMCOUNTERS];
> >> -
> >> -/* for RV32 */
> >> -target_ulong mhpmcounterh_val[RV_MAX_MHPMCOUNTERS];
> >> +/* PMU counter state */
> >> +PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
> >>
> >> -/* PMU event selector configured values */
> >> +/* PMU event selector configured values. First three are unused*/
> >>  target_ulong mhpmevent_val[RV_MAX_MHPMEVENTS];
> >>
> >>  target_ulong sscratch;
> >> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> >> index 87aa601e5ddb..c050ed2e2c1b 100644
> >> --- a/target/riscv/csr.c
> >> +++ b/target/riscv/csr.c
> >> @@ -21,6 +21,7 @@
> >>  #include "qemu/log.h"
> >>  #include "qemu/timer.h"
> >>  #include "cpu.h"
> >> +#include "pmu.h"
> >>  #include "qemu/main-loop.h"
> >>  #include "exec/exec-all.h"
> >>  #include "sysemu/cpu-timers.h"
> >> @@ -597,34 +598,28 @@ static int write_vcsr(CPURISCVState *env, int
> csrno, target_ulong val)
> >>  }
> >>
> >>  /* User Timers and Counters */
> >> -static RISCVException read_instret(CPURISCVState *env, int csrno,
> >> -   target_ulong *val)
> >> +static target_ulong get_ticks(bool shift)
> >>  {
> >> +int64_t val;
> >> +target_ulong result;
> >> +
> >>  #if !defined(CONFIG_USER_ONLY)
> >>  if (icount_enabled()) {
> >> -*val = icount_get();
> >> +val = icount_get();
> >>  } else {
> >> -*val = cpu_get_host_ticks();
> >> +val = cpu_get_host_ticks();
> >>  }
> >>  #else
> >> -*val = cpu_get_host_ticks();
> >> +val = cpu_get_host_ticks();
> >>  #endif
> >> -return RISCV_EXCP_NONE;
> >> -}
> >>
> >> -static RISCVException read_instreth(CPURISCVState *env, int csrno,
> >> -target_ulong *val)
> >> -{
> >> -#if !defined(CONFIG_USER_ONLY)
> >> -if (icount_enabled()) {
> >> -*val = icount_get() >> 32;
> >> +if (shift) {
> >> +result = val >> 32;
> >>  } else {
> >> -*val = cpu_get_host_ticks() >> 32;
> >> +result = val;
> >>  }
> >> -#else
> >> -*val = cpu_get_host_ticks() >> 32;
> >> -#endif
> >> -return RISCV_EXCP_NONE;
> >> +
> >> +return result;
> >>  }
> >>
> >>  #if defined(CONFIG_USER_ONLY)
> >> @@ -642,11 +637,23 @@ static RISCVException read_timeh(CPURISCVState
> *env, int csrno,
> >>  return RISCV_EXCP_NONE;
> >>  }
> >>
> >> +static int read_hpmcounter(CPURISCVState *env, int csrno, target_ulong
> *val)
> >> +{
> >> +*val = get_ticks(false);
> >> +return RISCV_EXCP_NONE;
> >> 

Re: [PATCH v8 07/12] target/riscv: Support mcycle/minstret write operation

2022-05-13 Thread Atish Kumar Patra
On Thu, May 12, 2022 at 11:29 PM Frank Chang  wrote:
>
> On Thu, May 12, 2022 at 6:01 AM Atish Patra  wrote:
>>
>> From: Atish Patra 
>>
>> mcycle/minstret are actually WARL registers and can be written with any
>> given value. With SBI PMU extension, it will be used to store a initial
>> value provided from supervisor OS. The Qemu also need prohibit the counter
>> increment if mcountinhibit is set.
>>
>> Support mcycle/minstret through generic counter infrastructure.
>>
>> Reviewed-by: Alistair Francis 
>> Signed-off-by: Atish Patra 
>> Signed-off-by: Atish Patra 
>> ---
>>  target/riscv/cpu.h   |  23 --
>>  target/riscv/csr.c   | 157 ---
>>  target/riscv/machine.c   |  25 ++-
>>  target/riscv/meson.build |   3 +-
>>  target/riscv/pmu.c   |  32 
>>  target/riscv/pmu.h   |  28 +++
>>  6 files changed, 214 insertions(+), 54 deletions(-)
>>  create mode 100644 target/riscv/pmu.c
>>  create mode 100644 target/riscv/pmu.h
>>
>> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
>> index 32cdd9070be5..f60072e0fd3d 100644
>> --- a/target/riscv/cpu.h
>> +++ b/target/riscv/cpu.h
>> @@ -111,7 +111,7 @@ typedef struct CPUArchState CPURISCVState;
>>  #endif
>>
>>  #define RV_VLEN_MAX 1024
>> -#define RV_MAX_MHPMEVENTS 29
>> +#define RV_MAX_MHPMEVENTS 32
>>  #define RV_MAX_MHPMCOUNTERS 32
>>
>>  FIELD(VTYPE, VLMUL, 0, 3)
>> @@ -121,6 +121,18 @@ FIELD(VTYPE, VMA, 7, 1)
>>  FIELD(VTYPE, VEDIV, 8, 2)
>>  FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11)
>>
>> +typedef struct PMUCTRState {
>> +/* Current value of a counter */
>> +target_ulong mhpmcounter_val;
>> +/* Current value of a counter in RV32*/
>> +target_ulong mhpmcounterh_val;
>> +/* Snapshot values of counter */
>> +target_ulong mhpmcounter_prev;
>> +/* Snapshort value of a counter in RV32 */
>> +target_ulong mhpmcounterh_prev;
>> +bool started;
>> +} PMUCTRState;
>> +
>>  struct CPUArchState {
>>  target_ulong gpr[32];
>>  target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
>> @@ -273,13 +285,10 @@ struct CPUArchState {
>>
>>  target_ulong mcountinhibit;
>>
>> -/* PMU counter configured values */
>> -target_ulong mhpmcounter_val[RV_MAX_MHPMCOUNTERS];
>> -
>> -/* for RV32 */
>> -target_ulong mhpmcounterh_val[RV_MAX_MHPMCOUNTERS];
>> +/* PMU counter state */
>> +PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
>>
>> -/* PMU event selector configured values */
>> +/* PMU event selector configured values. First three are unused*/
>>  target_ulong mhpmevent_val[RV_MAX_MHPMEVENTS];
>>
>>  target_ulong sscratch;
>> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
>> index 87aa601e5ddb..c050ed2e2c1b 100644
>> --- a/target/riscv/csr.c
>> +++ b/target/riscv/csr.c
>> @@ -21,6 +21,7 @@
>>  #include "qemu/log.h"
>>  #include "qemu/timer.h"
>>  #include "cpu.h"
>> +#include "pmu.h"
>>  #include "qemu/main-loop.h"
>>  #include "exec/exec-all.h"
>>  #include "sysemu/cpu-timers.h"
>> @@ -597,34 +598,28 @@ static int write_vcsr(CPURISCVState *env, int csrno, 
>> target_ulong val)
>>  }
>>
>>  /* User Timers and Counters */
>> -static RISCVException read_instret(CPURISCVState *env, int csrno,
>> -   target_ulong *val)
>> +static target_ulong get_ticks(bool shift)
>>  {
>> +int64_t val;
>> +target_ulong result;
>> +
>>  #if !defined(CONFIG_USER_ONLY)
>>  if (icount_enabled()) {
>> -*val = icount_get();
>> +val = icount_get();
>>  } else {
>> -*val = cpu_get_host_ticks();
>> +val = cpu_get_host_ticks();
>>  }
>>  #else
>> -*val = cpu_get_host_ticks();
>> +val = cpu_get_host_ticks();
>>  #endif
>> -return RISCV_EXCP_NONE;
>> -}
>>
>> -static RISCVException read_instreth(CPURISCVState *env, int csrno,
>> -target_ulong *val)
>> -{
>> -#if !defined(CONFIG_USER_ONLY)
>> -if (icount_enabled()) {
>> -*val = icount_get() >> 32;
>> +if (shift) {
>> +result = val >> 32;
>>  } else {
>> -*val = cpu_get_host_ticks() >> 32;
>> +result = val;
>>  }
>> -#else
>> -*val = cpu_get_host_ticks() >> 32;
>> -#endif
>> -return RISCV_EXCP_NONE;
>> +
>> +return result;
>>  }
>>
>>  #if defined(CONFIG_USER_ONLY)
>> @@ -642,11 +637,23 @@ static RISCVException read_timeh(CPURISCVState *env, 
>> int csrno,
>>  return RISCV_EXCP_NONE;
>>  }
>>
>> +static int read_hpmcounter(CPURISCVState *env, int csrno, target_ulong *val)
>> +{
>> +*val = get_ticks(false);
>> +return RISCV_EXCP_NONE;
>> +}
>> +
>> +static int read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong 
>> *val)
>> +{
>> +*val = get_ticks(true);
>> +return RISCV_EXCP_NONE;
>> +}
>> +
>>  #else /* CONFIG_USER_ONLY */
>>
>>  static int read_mhpmevent(CPURISCVState *env, int csrno, target_ulong *val)
>>  {
>> -int evt_index = csrno - CSR_MHPMEVENT3;
>> + 

Re: [PATCH v8 07/12] target/riscv: Support mcycle/minstret write operation

2022-05-13 Thread Frank Chang
On Thu, May 12, 2022 at 6:01 AM Atish Patra  wrote:

> From: Atish Patra 
>
> mcycle/minstret are actually WARL registers and can be written with any
> given value. With SBI PMU extension, it will be used to store a initial
> value provided from supervisor OS. The Qemu also need prohibit the counter
> increment if mcountinhibit is set.
>
> Support mcycle/minstret through generic counter infrastructure.
>
> Reviewed-by: Alistair Francis 
> Signed-off-by: Atish Patra 
> Signed-off-by: Atish Patra 
> ---
>  target/riscv/cpu.h   |  23 --
>  target/riscv/csr.c   | 157 ---
>  target/riscv/machine.c   |  25 ++-
>  target/riscv/meson.build |   3 +-
>  target/riscv/pmu.c   |  32 
>  target/riscv/pmu.h   |  28 +++
>  6 files changed, 214 insertions(+), 54 deletions(-)
>  create mode 100644 target/riscv/pmu.c
>  create mode 100644 target/riscv/pmu.h
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 32cdd9070be5..f60072e0fd3d 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -111,7 +111,7 @@ typedef struct CPUArchState CPURISCVState;
>  #endif
>
>  #define RV_VLEN_MAX 1024
> -#define RV_MAX_MHPMEVENTS 29
> +#define RV_MAX_MHPMEVENTS 32
>  #define RV_MAX_MHPMCOUNTERS 32
>
>  FIELD(VTYPE, VLMUL, 0, 3)
> @@ -121,6 +121,18 @@ FIELD(VTYPE, VMA, 7, 1)
>  FIELD(VTYPE, VEDIV, 8, 2)
>  FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11)
>
> +typedef struct PMUCTRState {
> +/* Current value of a counter */
> +target_ulong mhpmcounter_val;
> +/* Current value of a counter in RV32*/
> +target_ulong mhpmcounterh_val;
> +/* Snapshot values of counter */
> +target_ulong mhpmcounter_prev;
> +/* Snapshort value of a counter in RV32 */
> +target_ulong mhpmcounterh_prev;
> +bool started;
> +} PMUCTRState;
> +
>  struct CPUArchState {
>  target_ulong gpr[32];
>  target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
> @@ -273,13 +285,10 @@ struct CPUArchState {
>
>  target_ulong mcountinhibit;
>
> -/* PMU counter configured values */
> -target_ulong mhpmcounter_val[RV_MAX_MHPMCOUNTERS];
> -
> -/* for RV32 */
> -target_ulong mhpmcounterh_val[RV_MAX_MHPMCOUNTERS];
> +/* PMU counter state */
> +PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
>
> -/* PMU event selector configured values */
> +/* PMU event selector configured values. First three are unused*/
>  target_ulong mhpmevent_val[RV_MAX_MHPMEVENTS];
>
>  target_ulong sscratch;
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 87aa601e5ddb..c050ed2e2c1b 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -21,6 +21,7 @@
>  #include "qemu/log.h"
>  #include "qemu/timer.h"
>  #include "cpu.h"
> +#include "pmu.h"
>  #include "qemu/main-loop.h"
>  #include "exec/exec-all.h"
>  #include "sysemu/cpu-timers.h"
> @@ -597,34 +598,28 @@ static int write_vcsr(CPURISCVState *env, int csrno,
> target_ulong val)
>  }
>
>  /* User Timers and Counters */
> -static RISCVException read_instret(CPURISCVState *env, int csrno,
> -   target_ulong *val)
> +static target_ulong get_ticks(bool shift)
>  {
> +int64_t val;
> +target_ulong result;
> +
>  #if !defined(CONFIG_USER_ONLY)
>  if (icount_enabled()) {
> -*val = icount_get();
> +val = icount_get();
>  } else {
> -*val = cpu_get_host_ticks();
> +val = cpu_get_host_ticks();
>  }
>  #else
> -*val = cpu_get_host_ticks();
> +val = cpu_get_host_ticks();
>  #endif
> -return RISCV_EXCP_NONE;
> -}
>
> -static RISCVException read_instreth(CPURISCVState *env, int csrno,
> -target_ulong *val)
> -{
> -#if !defined(CONFIG_USER_ONLY)
> -if (icount_enabled()) {
> -*val = icount_get() >> 32;
> +if (shift) {
> +result = val >> 32;
>  } else {
> -*val = cpu_get_host_ticks() >> 32;
> +result = val;
>  }
> -#else
> -*val = cpu_get_host_ticks() >> 32;
> -#endif
> -return RISCV_EXCP_NONE;
> +
> +return result;
>  }
>
>  #if defined(CONFIG_USER_ONLY)
> @@ -642,11 +637,23 @@ static RISCVException read_timeh(CPURISCVState *env,
> int csrno,
>  return RISCV_EXCP_NONE;
>  }
>
> +static int read_hpmcounter(CPURISCVState *env, int csrno, target_ulong
> *val)
> +{
> +*val = get_ticks(false);
> +return RISCV_EXCP_NONE;
> +}
> +
> +static int read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong
> *val)
> +{
> +*val = get_ticks(true);
> +return RISCV_EXCP_NONE;
> +}
> +
>  #else /* CONFIG_USER_ONLY */
>
>  static int read_mhpmevent(CPURISCVState *env, int csrno, target_ulong
> *val)
>  {
> -int evt_index = csrno - CSR_MHPMEVENT3;
> +int evt_index = csrno - CSR_MCOUNTINHIBIT;
>
>  *val = env->mhpmevent_val[evt_index];
>
> @@ -655,7 +662,7 @@ static int read_mhpmevent(CPURISCVState *env, int
> csrno, target_ulong *val)
>
>  static int