Signed-off-by: Luis Cunha <[email protected]>
---
 target/riscv/cpu_bits.h           |  4 ++
 target/riscv/cpu_cfg_fields.h.inc |  1 +
 target/riscv/csr.c                | 67 +++++++++++++++++++++++++++++++
 target/riscv/spmp.c               |  6 ++-
 4 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 36f7c1e873..0a8cfedc5d 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -255,6 +255,10 @@
 #define CSR_SCTRSTATUS      0x14f
 #define CSR_SCTRDEPTH       0x15f
 
+/* S-mode Physical Memory Protection (SPMP) */
+#define CSR_SPMPEN          0x183
+#define CSR_SPMPENH         0x193
+
 /* VS-Level Control transfer records CSRs */
 #define CSR_VSCTRCTL        0x24e
 
diff --git a/target/riscv/cpu_cfg_fields.h.inc 
b/target/riscv/cpu_cfg_fields.h.inc
index 772cc176d0..88edac21ca 100644
--- a/target/riscv/cpu_cfg_fields.h.inc
+++ b/target/riscv/cpu_cfg_fields.h.inc
@@ -120,6 +120,7 @@ BOOL_FIELD(rvv_ma_all_1s)
 BOOL_FIELD(rvv_vl_half_avl)
 BOOL_FIELD(rvv_vsetvl_x0_vill)
 BOOL_FIELD(ext_smpmpdeleg)
+BOOL_FIELD(ext_sspmpen)
 /* Named features  */
 BOOL_FIELD(ext_svade)
 BOOL_FIELD(ext_zic64b)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 4b9fa11540..a11d7e6704 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -769,6 +769,16 @@ static RISCVException spmp(CPURISCVState *env, int csrno)
     return smode(env, csrno);
 }
 
+static RISCVException sspmpen(CPURISCVState *env, int csrno)
+{
+    if (!riscv_cpu_cfg(env)->ext_sspmpen) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+
+    /* SSPMPEN can only exist, if spmp exists */
+    return spmp(env, csrno);
+}
+
 static RISCVException have_mseccfg(CPURISCVState *env, int csrno)
 {
     if (riscv_cpu_cfg(env)->ext_smepmp) {
@@ -5389,6 +5399,61 @@ static RISCVException rmw_mpmpdeleg(CPURISCVState *env, 
int csrno,
     return RISCV_EXCP_NONE;
 }
 
+static RISCVException rmw_spmpen64(CPURISCVState *env, int csrno,
+                                    uint64_t *ret_val,
+                                    uint64_t new_val, uint64_t wr_mask)
+{
+    uint64_t new_spmpen = (env->spmp_state.spmpen & ~wr_mask) |
+                            (new_val & wr_mask);
+
+    if (env->spmp_state.num_deleg_rules == 0) {
+        if (ret_val) {
+            *ret_val = 0;
+        }
+
+        return RISCV_EXCP_NONE;
+    }
+
+    if (ret_val) {
+        *ret_val = env->spmp_state.spmpen;
+    }
+
+    sspmpen_csr_write(env, new_spmpen);
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException rmw_spmpen(CPURISCVState *env, int csrno,
+                                  target_ulong *ret_val,
+                                  target_ulong new_val, target_ulong wr_mask)
+{
+    uint64_t rval = 0;
+    RISCVException ret;
+    ret = rmw_spmpen64(env, csrno, &rval, new_val, wr_mask);
+    if (ret_val) {
+        *ret_val = rval;
+    }
+
+    return ret;
+}
+
+static RISCVException rmw_spmpenh(CPURISCVState *env, int csrno,
+                                   target_ulong *ret_val,
+                                   target_ulong new_val,
+                                   target_ulong wr_mask)
+{
+    uint64_t rval = 0;
+    RISCVException ret;
+
+    ret = rmw_spmpen64(env, csrno, &rval,
+        ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
+    if (ret_val) {
+        *ret_val = rval >> 32;
+    }
+
+    return ret;
+}
+
 static RISCVException read_tselect(CPURISCVState *env, int csrno,
                                    target_ulong *val)
 {
@@ -6388,6 +6453,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 
     /* S-mode Physical Memory Protection */
     [CSR_MPMPDELEG]   = { "mpmpdeleg", spmp, NULL, NULL, rmw_mpmpdeleg },
+    [CSR_SPMPEN]  = { "spmpen", sspmpen, NULL, NULL, rmw_spmpen },
+    [CSR_SPMPENH] = { "spmpenh", sspmpen, NULL, NULL, rmw_spmpenh },
 
     /* Debug CSRs */
     [CSR_TSELECT]   =  { "tselect",  debug, read_tselect,  write_tselect  },
diff --git a/target/riscv/spmp.c b/target/riscv/spmp.c
index 85c5259b33..1615c207df 100644
--- a/target/riscv/spmp.c
+++ b/target/riscv/spmp.c
@@ -147,7 +147,11 @@ static uint8_t spmp_is_in_range(CPURISCVState *env, int 
spmp_index,
 
 static bool spmp_get_spmpen_bit(CPURISCVState *env, int index)
 {
-    return true;
+    if (!riscv_cpu_cfg(env)->ext_sspmpen) {
+        return true;
+    }
+
+    return (env->spmp_state.spmpen >> index) & 0x1;
 }
 
 /*
-- 
2.43.0


Reply via email to