diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/riscv/cpu.h | 1 | ||||
-rw-r--r-- | target/riscv/csr.c | 34 | ||||
-rw-r--r-- | target/riscv/machine.c | 5 |
3 files changed, 24 insertions, 16 deletions
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index f515ad0..093c86b 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -176,7 +176,6 @@ typedef struct PMUCTRState { target_ulong mhpmcounter_prev; /* Snapshort value of a counter in RV32 */ target_ulong mhpmcounterh_prev; - bool started; /* Value beyond UINT32_MAX/UINT64_MAX before overflow interrupt trigger */ target_ulong irq_overflow_left; } PMUCTRState; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 85d3f0a..b7a24f9 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1131,17 +1131,11 @@ static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val, if (get_field(env->mcountinhibit, BIT(ctr_idx))) { /* - * Counter should not increment if inhibit bit is set. We can't really - * stop the icount counting. Just return the counter value written by - * the supervisor to indicate that counter was not incremented. + * Counter should not increment if inhibit bit is set. Just return the + * current counter value. */ - if (!counter->started) { - *val = ctr_val; - return RISCV_EXCP_NONE; - } else { - /* Mark that the counter has been stopped */ - counter->started = false; - } + *val = ctr_val; + return RISCV_EXCP_NONE; } /* @@ -2183,9 +2177,25 @@ static RISCVException write_mcountinhibit(CPURISCVState *env, int csrno, /* Check if any other counter is also monitoring cycles/instructions */ for (cidx = 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) { - if (!get_field(env->mcountinhibit, BIT(cidx))) { counter = &env->pmu_ctrs[cidx]; - counter->started = true; + 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 (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; + } + } } } diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 76f2150..492c2c6 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -320,15 +320,14 @@ static bool pmu_needed(void *opaque) static const VMStateDescription vmstate_pmu_ctr_state = { .name = "cpu/pmu", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .needed = pmu_needed, .fields = (const VMStateField[]) { VMSTATE_UINTTL(mhpmcounter_val, PMUCTRState), VMSTATE_UINTTL(mhpmcounterh_val, PMUCTRState), VMSTATE_UINTTL(mhpmcounter_prev, PMUCTRState), VMSTATE_UINTTL(mhpmcounterh_prev, PMUCTRState), - VMSTATE_BOOL(started, PMUCTRState), VMSTATE_END_OF_LIST() } }; |