在 2022/6/21 上午7:15, Atish Patra 写道:
All the hpmcounters and the fixed counters (CY, IR, TM) can be represented
as a unified counter. Thus, the predicate function doesn't need handle each
case separately.
Simplify the predicate function so that we just handle things differently
between RV32/RV64 and S/HS mode.
Reviewed-by: Bin Meng <bmeng...@gmail.com>
Acked-by: Alistair Francis <alistair.fran...@wdc.com>
Signed-off-by: Atish Patra <ati...@rivosinc.com>
---
target/riscv/csr.c | 112 +++++----------------------------------------
1 file changed, 11 insertions(+), 101 deletions(-)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 2664ce265784..9367e2af9b90 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -74,6 +74,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
CPUState *cs = env_cpu(env);
RISCVCPU *cpu = RISCV_CPU(cs);
int ctr_index;
+ target_ulong ctr_mask;
int base_csrno = CSR_CYCLE;
bool rv32 = riscv_cpu_mxl(env) == MXL_RV32 ? true : false;
@@ -82,122 +83,31 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
base_csrno += 0x80;
}
ctr_index = csrno - base_csrno;
+ ctr_mask = BIT(ctr_index);
if ((csrno >= CSR_CYCLE && csrno <= CSR_INSTRET) ||
(csrno >= CSR_CYCLEH && csrno <= CSR_INSTRETH)) {
goto skip_ext_pmu_check;
}
- if ((!cpu->cfg.pmu_num || !(cpu->pmu_avail_ctrs & BIT(ctr_index)))) {
+ if ((!cpu->cfg.pmu_num || !(cpu->pmu_avail_ctrs & ctr_mask))) {
/* No counter is enabled in PMU or the counter is out of range */
return RISCV_EXCP_ILLEGAL_INST;
}
skip_ext_pmu_check:
- if (env->priv == PRV_S) {
- switch (csrno) {
- case CSR_CYCLE:
- if (!get_field(env->mcounteren, COUNTEREN_CY)) {
- return RISCV_EXCP_ILLEGAL_INST;
- }
- break;
- case CSR_TIME:
- if (!get_field(env->mcounteren, COUNTEREN_TM)) {
- return RISCV_EXCP_ILLEGAL_INST;
- }
- break;
- case CSR_INSTRET:
- if (!get_field(env->mcounteren, COUNTEREN_IR)) {
- return RISCV_EXCP_ILLEGAL_INST;
- }
- break;
- case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31:
- if (!get_field(env->mcounteren, 1 << ctr_index)) {
- return RISCV_EXCP_ILLEGAL_INST;
- }
- break;
- }
- if (rv32) {
- switch (csrno) {
- case CSR_CYCLEH:
- if (!get_field(env->mcounteren, COUNTEREN_CY)) {
- return RISCV_EXCP_ILLEGAL_INST;
- }
- break;
- case CSR_TIMEH:
- if (!get_field(env->mcounteren, COUNTEREN_TM)) {
- return RISCV_EXCP_ILLEGAL_INST;
- }
- break;
- case CSR_INSTRETH:
- if (!get_field(env->mcounteren, COUNTEREN_IR)) {
- return RISCV_EXCP_ILLEGAL_INST;
- }
- break;
- case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
- if (!get_field(env->mcounteren, 1 << ctr_index)) {
- return RISCV_EXCP_ILLEGAL_INST;
- }
- break;
- }
- }
+ if (((env->priv == PRV_S) && (!get_field(env->mcounteren, ctr_mask))) ||
+ ((env->priv == PRV_U) && (!get_field(env->scounteren, ctr_mask)))) {
+ return RISCV_EXCP_ILLEGAL_INST;
}
Sorry. I didn't realize this simplification and sent a similar patch to
fix the problems in Xcounteren
related check I found when I tried to learn the patchset for state
enable extension two days ago.
I think there are several difference between our understanding,
following is my modifications:
+ 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;
}
}
1) For any less-privileged mode under M, illegal exception is raised if matching
bit in mcounteren is zero.
2) For VS/VU mode('H' extension is supported implicitly), virtual instruction
exception is raised if matching bit in hcounteren is zero.
3) scounteren csr only works in U/VU mode when 'S' extension is supported:
For U mode, illegal exception is raised if matching bit in scounteren is
zero.
For VU mode, virtual instruction exception exception is raised if matching
bit
in scounteren is zero.
Regards,
Weiwei Li
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 << ctr_index) &&
- get_field(env->mcounteren, 1 << ctr_index)) {
- return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
- }
- break;
- }
- if (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 << ctr_index) &&
- get_field(env->mcounteren, 1 << ctr_index)) {
- return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
- }
- break;
- }
+ if (!get_field(env->mcounteren, ctr_mask)) {
+ /* The bit must be set in mcountern for HS mode access */
+ return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ } else if (!get_field(env->hcounteren, ctr_mask)) {
+ return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
}
}
#endif