- improve the field extract progress - add stand-alone check for mcuonteren when in less-privileged mode - add check for scounteren when 'S' is enabled and current priv is PRV_U
Signed-off-by: Weiwei Li <liwei...@iscas.ac.cn> Signed-off-by: Junqiang Wang <wangjunqi...@iscas.ac.cn> --- target/riscv/csr.c | 76 ++++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 54 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 6dbe9b541f..a4719cbf35 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -72,66 +72,34 @@ static RISCVException ctr(CPURISCVState *env, int csrno) #if !defined(CONFIG_USER_ONLY) CPUState *cs = env_cpu(env); RISCVCPU *cpu = RISCV_CPU(cs); + uint32_t field = 0; if (!cpu->cfg.ext_counters) { /* The Counters extensions is not enabled */ return RISCV_EXCP_ILLEGAL_INST; } - if (riscv_cpu_virt_enabled(env)) { - switch (csrno) { - case CSR_CYCLE: - if (!get_field(env->hcounteren, COUNTEREN_CY) && - get_field(env->mcounteren, COUNTEREN_CY)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - case CSR_TIME: - if (!get_field(env->hcounteren, COUNTEREN_TM) && - get_field(env->mcounteren, COUNTEREN_TM)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - case CSR_INSTRET: - if (!get_field(env->hcounteren, COUNTEREN_IR) && - get_field(env->mcounteren, COUNTEREN_IR)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31: - if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3)) && - get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3))) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - } - if (riscv_cpu_mxl(env) == MXL_RV32) { - switch (csrno) { - case CSR_CYCLEH: - if (!get_field(env->hcounteren, COUNTEREN_CY) && - get_field(env->mcounteren, COUNTEREN_CY)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - case CSR_TIMEH: - if (!get_field(env->hcounteren, COUNTEREN_TM) && - get_field(env->mcounteren, COUNTEREN_TM)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - case CSR_INSTRETH: - if (!get_field(env->hcounteren, COUNTEREN_IR) && - get_field(env->mcounteren, COUNTEREN_IR)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H: - if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3H)) && - get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3H))) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - } + if (csrno <= CSR_HPMCOUNTER31 && csrno >= CSR_CYCLE) { + field = 1 << (csrno - CSR_CYCLE); + } else if (riscv_cpu_mxl(env) == MXL_RV32 && csrno <= CSR_HPMCOUNTER31H && + csrno >= CSR_CYCLEH) { + field = 1 << (csrno - CSR_CYCLEH); + } + + if (env->priv < PRV_M && !get_field(env->mcounteren, field)) { + return RISCV_EXCP_ILLEGAL_INST; + } + + if (riscv_cpu_virt_enabled(env) && !get_field(env->hcounteren, field)) { + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; + } + + if (riscv_has_ext(env, RVS) && env->priv == PRV_U && + !get_field(env->scounteren, field)) { + if (riscv_cpu_virt_enabled(env)) { + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; + } else { + return RISCV_EXCP_ILLEGAL_INST; } } #endif -- 2.17.1