[PULL 17/17] target/riscv: Fix scountovf CSR behavior in VS-mode and M-mode

alistair23@gmail.com posted 17 patches 2 days, 14 hours ago
Maintainers: Pierrick Bouvier <pierrick.bouvier@linaro.org>, Aurelien Jarno <aurelien@aurel32.net>, Peter Maydell <peter.maydell@linaro.org>, "Alex Bennée" <alex.bennee@linaro.org>, Alistair Francis <Alistair.Francis@wdc.com>, Palmer Dabbelt <palmer@dabbelt.com>, "Marc-André Lureau" <marcandre.lureau@redhat.com>, Paolo Bonzini <pbonzini@redhat.com>, Weiwei Li <liwei1518@gmail.com>, Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>, Liu Zhiwei <zhiwei_liu@linux.alibaba.com>, Chao Liu <chao.liu.zevorn@gmail.com>
There is a newer version of this series
[PULL 17/17] target/riscv: Fix scountovf CSR behavior in VS-mode and M-mode
Posted by alistair23@gmail.com 2 days, 14 hours ago
From: Jim Shu <jim.shu@sifive.com>

From Sscofpmf spec [1]:
- In M-mode, scountovf bit X is always readable.
- in VS mode, scountovf bit X is readable when mcounteren bit X and
  hcounteren bit X are both set, and otherwise reads as zero.

[1] https://github.com/riscv/riscv-isa-manual/blob/main/src/sscofpmf.adoc

Signed-off-by: Jim Shu <jim.shu@sifive.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20260318024234.2772480-1-jim.shu@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 target/riscv/csr.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 5064483917..a75281539b 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1599,6 +1599,7 @@ static RISCVException read_scountovf(CPURISCVState *env, int csrno,
     int mhpmevt_start = CSR_MHPMEVENT3 - CSR_MCOUNTINHIBIT;
     int i;
     *val = 0;
+    bool virt = env->virt_enabled;
 
     /* Virtualize scountovf for counter delegation */
     if (riscv_cpu_cfg(env)->ext_sscofpmf &&
@@ -1609,8 +1610,19 @@ static RISCVException read_scountovf(CPURISCVState *env, int csrno,
     }
 
     for (i = mhpmevt_start; i < RV_MAX_MHPMEVENTS; i++) {
-        if ((get_field(env->mcounteren, BIT(i))) &&
-            (env->mhpmevent_val[i] & MHPMEVENT_BIT_OF)) {
+        if (env->priv < PRV_M) {
+            if (!get_field(env->mcounteren, BIT(i))) {
+                /* no mcounteren in S/HS-mode */
+                continue;
+            }
+
+            if (virt && !get_field(env->hcounteren, BIT(i))) {
+                /* no hcounteren in VS-mode */
+                continue;
+            }
+        }
+
+        if (env->mhpmevent_val[i] & MHPMEVENT_BIT_OF) {
             *val |= BIT(i);
         }
     }
-- 
2.53.0