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