aboutsummaryrefslogtreecommitdiff
path: root/target/riscv/csr.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/riscv/csr.c')
-rw-r--r--target/riscv/csr.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 46bd417cc1..58d07c511f 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -79,6 +79,57 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
return RISCV_EXCP_ILLEGAL_INST;
}
+ 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:
+ ctr_index = csrno - CSR_CYCLE;
+ if (!get_field(env->mcounteren, 1 << ctr_index)) {
+ return RISCV_EXCP_ILLEGAL_INST;
+ }
+ break;
+ }
+ if (riscv_cpu_mxl(env) == MXL_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:
+ ctr_index = csrno - CSR_CYCLEH;
+ if (!get_field(env->mcounteren, 1 << ctr_index)) {
+ return RISCV_EXCP_ILLEGAL_INST;
+ }
+ break;
+ }
+ }
+ }
+
if (riscv_cpu_virt_enabled(env)) {
switch (csrno) {
case CSR_CYCLE: