Re: [PATCH v8 07/12] target/riscv: Support mcycle/minstret write operation
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
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
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
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