Introduce the CSR definitions and handlers  to configure S-mode Physical Memory 
Protection (SPMP).
This patch adds the SPMP CSR bit definitions. The implementation allows 
software to configure SPMP state but does not yet enforce memory access checks.

Signed-off-by: Luis Cunha <[email protected]>
---
 target/riscv/cpu_bits.h |  3 ++
 target/riscv/csr.c      | 73 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index b62dd82fe7..9b7ab28bba 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -1049,6 +1049,9 @@ typedef enum CTRType {
 #define ISELECT_CD_LAST                    0x5f
 #define ISELECT_MASK_SXCSRIND              0xfff
 
+/* SPMP Values for Indirect CSR Access Extension */
+#define ISELECT_SPMP_BASE                  0x100
+
 /* Dummy [M|S|VS]ISELECT value for emulating [M|S|VS]TOPEI CSRs */
 #define ISELECT_IMSIC_TOPEI                (ISELECT_MASK_AIA + 1)
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 5064483917..167d84d92a 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -759,6 +759,16 @@ static RISCVException pmp(CPURISCVState *env, int csrno)
     return RISCV_EXCP_ILLEGAL_INST;
 }
 
+static RISCVException spmp(CPURISCVState *env, int csrno)
+{
+    if (!riscv_cpu_cfg(env)->spmp) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+
+    /* SPMP can only exist, if smode exists */
+    return smode(env, csrno);
+}
+
 static RISCVException have_mseccfg(CPURISCVState *env, int csrno)
 {
     if (riscv_cpu_cfg(env)->ext_smepmp) {
@@ -2454,6 +2464,12 @@ static bool xiselect_ctr_range(int csrno, target_ulong 
isel)
            csrno < CSR_MIREG;
 }
 
+static bool xiselect_spmp_range(target_ulong isel)
+{
+    return (ISELECT_SPMP_BASE <= isel &&
+            isel <= ISELECT_SPMP_BASE + MAX_RISCV_SPMPS);
+}
+
 static int rmw_iprio(target_ulong xlen,
                      target_ulong iselect, uint8_t *iprio,
                      target_ulong *val, target_ulong new_val,
@@ -2790,6 +2806,9 @@ static int rmw_xireg_ctr(CPURISCVState *env, int csrno,
     return 0;
 }
 
+static int rmw_xireg_spmp(CPURISCVState *env, int csrno,
+                        target_ulong isel, target_ulong *val,
+                        target_ulong new_val, target_ulong wr_mask);
 /*
  * rmw_xireg_csrind: Perform indirect access to xireg and xireg2-xireg6
  *
@@ -2808,6 +2827,14 @@ static int rmw_xireg_csrind(CPURISCVState *env, int 
csrno,
         ret = rmw_xireg_cd(env, csrno, isel, val, new_val, wr_mask);
     } else if (xiselect_ctr_range(csrno, isel)) {
         ret = rmw_xireg_ctr(env, csrno, isel, val, new_val, wr_mask);
+    } else if (xiselect_spmp_range(isel)) {
+        /* Is SPMP enabled? */
+        ret = spmp(env, csrno);
+        if (ret != RISCV_EXCP_NONE) {
+            return ret;
+        }
+
+        ret = rmw_xireg_spmp(env, csrno, isel, val, new_val, wr_mask);
     } else {
         /*
          * As per the specification, access to unimplented region is undefined
@@ -5292,6 +5319,52 @@ static RISCVException write_pmpaddr(CPURISCVState *env, 
int csrno,
     return RISCV_EXCP_NONE;
 }
 
+static int rmw_xireg_spmp(CPURISCVState *env, int csrno,
+                        target_ulong isel, target_ulong *val,
+                        target_ulong new_val, target_ulong wr_mask)
+{
+    int index = 0;
+    bool m_mode_access = false;
+
+    /* Read 0 and write ignore if no rules are delegated */
+    if (env->spmp_state.num_deleg_rules == 0) {
+        *val = 0;
+        return 0;
+    }
+
+    index = isel - ISELECT_SPMP_BASE;
+
+    switch (csrno) {
+    case CSR_MIREG:
+        /* If M mode, signal it */
+        m_mode_access = true;
+        [[fallthrough]];
+    case CSR_SIREG:
+        if (val) {
+            *val = spmpaddr_csr_read(env, index);
+        }
+
+        spmpaddr_csr_write(env, index, new_val & wr_mask, m_mode_access);
+        break;
+    case CSR_MIREG2:
+        /* If M mode, signal it */
+        m_mode_access = true;
+        [[fallthrough]];
+    case CSR_SIREG2:
+        index = isel - ISELECT_SPMP_BASE;
+        if (val) {
+            *val = spmpcfg_csr_read(env, index);
+        }
+
+        spmpcfg_csr_write(env, index, new_val & wr_mask, m_mode_access);
+        break;
+    default:
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+
+    return 0;
+}
+
 static RISCVException read_tselect(CPURISCVState *env, int csrno,
                                    target_ulong *val)
 {
-- 
2.43.0


Reply via email to