From 3506ee2fc6feee08e63d7a6d7e5f21b3f5c22f9b Mon Sep 17 00:00:00 2001 From: whensun Date: Fri, 19 Jun 2026 15:36:08 -0700 Subject: [PATCH] riscv: Fix counter access control --- arch/riscv/op_helper.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/riscv/op_helper.c b/arch/riscv/op_helper.c index 833170c3c..a7b28fdbd 100644 --- a/arch/riscv/op_helper.c +++ b/arch/riscv/op_helper.c @@ -114,7 +114,10 @@ static inline target_ulong get_counter_enabled_mask(CPUState *env) case PRV_S: return env->mcounteren; case PRV_U: - return riscv_has_ext(env, RISCV_FEATURE_RVS) ? env->scounteren : env->mcounteren; + if(riscv_has_ext(env, RISCV_FEATURE_RVS)) { + return env->mcounteren & env->scounteren; + } + return env->mcounteren; default: tlib_abortf("Invalid privilege level: %d", env->priv); return 0; @@ -187,11 +190,17 @@ void helper_raise_illegal_instruction(CPUState *env) static inline uint64_t get_minstret_current(CPUState *env) { + if(env->privilege_architecture >= RISCV_PRIV1_11 && (env->mcountinhibit & 0x4)) { + return env->minstret_snapshot_offset > 0 ? env->minstret_snapshot_offset - 1 : 0; + } return cpu_riscv_read_instret(env) - env->minstret_snapshot + env->minstret_snapshot_offset; } static inline uint64_t get_mcycles_current(CPUState *env) { + if(env->privilege_architecture >= RISCV_PRIV1_11 && (env->mcountinhibit & 0x1)) { + return env->mcycle_snapshot_offset > 0 ? env->mcycle_snapshot_offset - 1 : 0; + } uint64_t instructions = cpu_riscv_read_instret(env) - env->mcycle_snapshot + env->mcycle_snapshot_offset; return instructions_to_cycles(env, instructions); } @@ -516,7 +525,16 @@ inline void csr_write_helper(CPUState *env, target_ulong val_to_write, target_ul if(env->privilege_architecture == RISCV_PRIV1_09) { env->mucounteren = val_to_write; } else if(env->privilege_architecture >= RISCV_PRIV1_11) { + uint64_t current_mcycle = get_mcycles_current(env); + uint64_t current_minstret = get_minstret_current(env); + uint64_t current_instret = cpu_riscv_read_instret(env); + env->mcountinhibit = val_to_write; + + env->mcycle_snapshot_offset = current_mcycle; + env->mcycle_snapshot = current_instret; + env->minstret_snapshot_offset = current_minstret; + env->minstret_snapshot = current_instret; } break; case CSR_MSCOUNTEREN: