Message ID | 20240626-smcntrpmf_v7-v7-9-bb0f10af7fa9@rivosinc.com |
---|---|
State | New |
Headers | show |
Series | Add RISC-V ISA extension smcntrpmf support | expand |
On 6/26/24 8:57 PM, Atish Patra wrote: > From: Rajnesh Kanwal <rkanwal@rivosinc.com> > > Currently we start timer counter from write_mhpmcounter path only > without checking for mcountinhibit bit. This changes adds mcountinhibit > check and also programs the counter from write_mcountinhibit as well. > > When a counter is stopped using mcountinhibit we simply update > the value of the counter based on current host ticks and save > it for future reads. > > We don't need to disable running timer as pmu_timer_trigger_irq > will discard the interrupt if the counter has been inhibited. > > Signed-off-by: Rajnesh Kanwal <rkanwal@rivosinc.com> > --- Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> > target/riscv/csr.c | 75 ++++++++++++++++++++++++++++++++++++++---------------- > target/riscv/pmu.c | 3 +-- > 2 files changed, 54 insertions(+), 24 deletions(-) > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c > index 6c1a884eec82..150e02f080ec 100644 > --- a/target/riscv/csr.c > +++ b/target/riscv/csr.c > @@ -1008,8 +1008,9 @@ static RISCVException write_mhpmcounter(CPURISCVState *env, int csrno, > uint64_t mhpmctr_val = val; > > counter->mhpmcounter_val = val; > - if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || > - riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { > + if (!get_field(env->mcountinhibit, BIT(ctr_idx)) && > + (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || > + riscv_pmu_ctr_monitor_instructions(env, ctr_idx))) { > counter->mhpmcounter_prev = riscv_pmu_ctr_get_fixed_counters_val(env, > ctr_idx, false); > if (ctr_idx > 2) { > @@ -1037,8 +1038,9 @@ static RISCVException write_mhpmcounterh(CPURISCVState *env, int csrno, > > counter->mhpmcounterh_val = val; > mhpmctr_val = mhpmctr_val | (mhpmctrh_val << 32); > - if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || > - riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { > + if (!get_field(env->mcountinhibit, BIT(ctr_idx)) && > + (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || > + riscv_pmu_ctr_monitor_instructions(env, ctr_idx))) { > counter->mhpmcounterh_prev = riscv_pmu_ctr_get_fixed_counters_val(env, > ctr_idx, true); > if (ctr_idx > 2) { > @@ -2101,31 +2103,60 @@ static RISCVException write_mcountinhibit(CPURISCVState *env, int csrno, > int cidx; > PMUCTRState *counter; > RISCVCPU *cpu = env_archcpu(env); > + uint32_t present_ctrs = cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_IR; > + target_ulong updated_ctrs = (env->mcountinhibit ^ val) & present_ctrs; > + uint64_t mhpmctr_val, prev_count, curr_count; > > /* WARL register - disable unavailable counters; TM bit is always 0 */ > - env->mcountinhibit = > - val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_IR); > + env->mcountinhibit = val & present_ctrs; > > /* Check if any other counter is also monitoring cycles/instructions */ > for (cidx = 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) { > - counter = &env->pmu_ctrs[cidx]; > - if (get_field(env->mcountinhibit, BIT(cidx)) && (val & BIT(cidx))) { > - /* > - * Update the counter value for cycle/instret as we can't stop the > - * host ticks. But we should show the current value at this moment. > - */ > - if (riscv_pmu_ctr_monitor_cycles(env, cidx) || > - riscv_pmu_ctr_monitor_instructions(env, cidx)) { > - counter->mhpmcounter_val = > - riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false) - > - counter->mhpmcounter_prev + > - counter->mhpmcounter_val; > + if (!(updated_ctrs & BIT(cidx)) || > + (!riscv_pmu_ctr_monitor_cycles(env, cidx) && > + !riscv_pmu_ctr_monitor_instructions(env, cidx))) { > + continue; > + } > + > + counter = &env->pmu_ctrs[cidx]; > + > + if (!get_field(env->mcountinhibit, BIT(cidx))) { > + counter->mhpmcounter_prev = > + riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false); > + if (riscv_cpu_mxl(env) == MXL_RV32) { > + counter->mhpmcounterh_prev = > + riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true); > + } > + > + if (cidx > 2) { > + mhpmctr_val = counter->mhpmcounter_val; > if (riscv_cpu_mxl(env) == MXL_RV32) { > - counter->mhpmcounterh_val = > - riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true) - > - counter->mhpmcounterh_prev + > - counter->mhpmcounterh_val; > + mhpmctr_val = mhpmctr_val | > + ((uint64_t)counter->mhpmcounterh_val << 32); > } > + riscv_pmu_setup_timer(env, mhpmctr_val, cidx); > + } > + } else { > + curr_count = riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false); > + > + mhpmctr_val = counter->mhpmcounter_val; > + prev_count = counter->mhpmcounter_prev; > + if (riscv_cpu_mxl(env) == MXL_RV32) { > + uint64_t tmp = > + riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true); > + > + curr_count = curr_count | (tmp << 32); > + mhpmctr_val = mhpmctr_val | > + ((uint64_t)counter->mhpmcounterh_val << 32); > + prev_count = prev_count | > + ((uint64_t)counter->mhpmcounterh_prev << 32); > + } > + > + /* Adjust the counter for later reads. */ > + mhpmctr_val = curr_count - prev_count + mhpmctr_val; > + counter->mhpmcounter_val = mhpmctr_val; > + if (riscv_cpu_mxl(env) == MXL_RV32) { > + counter->mhpmcounterh_val = mhpmctr_val >> 32; > } > } > } > diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c > index ac648cff8d7c..63420d9f3679 100644 > --- a/target/riscv/pmu.c > +++ b/target/riscv/pmu.c > @@ -285,8 +285,7 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx) > } > > ctr_idx = GPOINTER_TO_UINT(value); > - if (!riscv_pmu_counter_enabled(cpu, ctr_idx) || > - get_field(env->mcountinhibit, BIT(ctr_idx))) { > + if (!riscv_pmu_counter_enabled(cpu, ctr_idx)) { > return -1; > } > >
diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 6c1a884eec82..150e02f080ec 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1008,8 +1008,9 @@ static RISCVException write_mhpmcounter(CPURISCVState *env, int csrno, uint64_t mhpmctr_val = val; counter->mhpmcounter_val = val; - if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || - riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { + if (!get_field(env->mcountinhibit, BIT(ctr_idx)) && + (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || + riscv_pmu_ctr_monitor_instructions(env, ctr_idx))) { counter->mhpmcounter_prev = riscv_pmu_ctr_get_fixed_counters_val(env, ctr_idx, false); if (ctr_idx > 2) { @@ -1037,8 +1038,9 @@ static RISCVException write_mhpmcounterh(CPURISCVState *env, int csrno, counter->mhpmcounterh_val = val; mhpmctr_val = mhpmctr_val | (mhpmctrh_val << 32); - if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || - riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { + if (!get_field(env->mcountinhibit, BIT(ctr_idx)) && + (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || + riscv_pmu_ctr_monitor_instructions(env, ctr_idx))) { counter->mhpmcounterh_prev = riscv_pmu_ctr_get_fixed_counters_val(env, ctr_idx, true); if (ctr_idx > 2) { @@ -2101,31 +2103,60 @@ static RISCVException write_mcountinhibit(CPURISCVState *env, int csrno, int cidx; PMUCTRState *counter; RISCVCPU *cpu = env_archcpu(env); + uint32_t present_ctrs = cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_IR; + target_ulong updated_ctrs = (env->mcountinhibit ^ val) & present_ctrs; + uint64_t mhpmctr_val, prev_count, curr_count; /* WARL register - disable unavailable counters; TM bit is always 0 */ - env->mcountinhibit = - val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_IR); + env->mcountinhibit = val & present_ctrs; /* Check if any other counter is also monitoring cycles/instructions */ for (cidx = 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) { - counter = &env->pmu_ctrs[cidx]; - if (get_field(env->mcountinhibit, BIT(cidx)) && (val & BIT(cidx))) { - /* - * Update the counter value for cycle/instret as we can't stop the - * host ticks. But we should show the current value at this moment. - */ - if (riscv_pmu_ctr_monitor_cycles(env, cidx) || - riscv_pmu_ctr_monitor_instructions(env, cidx)) { - counter->mhpmcounter_val = - riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false) - - counter->mhpmcounter_prev + - counter->mhpmcounter_val; + if (!(updated_ctrs & BIT(cidx)) || + (!riscv_pmu_ctr_monitor_cycles(env, cidx) && + !riscv_pmu_ctr_monitor_instructions(env, cidx))) { + continue; + } + + counter = &env->pmu_ctrs[cidx]; + + if (!get_field(env->mcountinhibit, BIT(cidx))) { + counter->mhpmcounter_prev = + riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false); + if (riscv_cpu_mxl(env) == MXL_RV32) { + counter->mhpmcounterh_prev = + riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true); + } + + if (cidx > 2) { + mhpmctr_val = counter->mhpmcounter_val; if (riscv_cpu_mxl(env) == MXL_RV32) { - counter->mhpmcounterh_val = - riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true) - - counter->mhpmcounterh_prev + - counter->mhpmcounterh_val; + mhpmctr_val = mhpmctr_val | + ((uint64_t)counter->mhpmcounterh_val << 32); } + riscv_pmu_setup_timer(env, mhpmctr_val, cidx); + } + } else { + curr_count = riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false); + + mhpmctr_val = counter->mhpmcounter_val; + prev_count = counter->mhpmcounter_prev; + if (riscv_cpu_mxl(env) == MXL_RV32) { + uint64_t tmp = + riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true); + + curr_count = curr_count | (tmp << 32); + mhpmctr_val = mhpmctr_val | + ((uint64_t)counter->mhpmcounterh_val << 32); + prev_count = prev_count | + ((uint64_t)counter->mhpmcounterh_prev << 32); + } + + /* Adjust the counter for later reads. */ + mhpmctr_val = curr_count - prev_count + mhpmctr_val; + counter->mhpmcounter_val = mhpmctr_val; + if (riscv_cpu_mxl(env) == MXL_RV32) { + counter->mhpmcounterh_val = mhpmctr_val >> 32; } } } diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index ac648cff8d7c..63420d9f3679 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -285,8 +285,7 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx) } ctr_idx = GPOINTER_TO_UINT(value); - if (!riscv_pmu_counter_enabled(cpu, ctr_idx) || - get_field(env->mcountinhibit, BIT(ctr_idx))) { + if (!riscv_pmu_counter_enabled(cpu, ctr_idx)) { return -1; }