[PATCH v7 01/11] target/riscv: Add basic definitions and CSRs for SMMPT

LIU Zhiwei <[email protected]>
Newsgroups org.nongnu.qemu-riscv,org.nongnu.qemu-devel
Message-ID <[email protected]>
This patch lays the groundwork for the SMMPT (Supervisor Domains Access
Protection) extension by introducing its fundamental components.

It adds:
- New CPU configuration flags, `ext_smmpt` and `ext_smsdid`, to enable
  the extension.
- Bit-field definitions for the `mmpt` CSR in `cpu_bits.h`.
- The `mmpt` and `msdcfg` CSR numbers and their read/write handlers in
  `csr.c`.
- New fields in `CPUArchState` to store the state of these new CSRs.
- A new translation failure reason `TRANSLATE_MPT_FAIL`.

This provides the necessary infrastructure for the core MPT logic and
MMU integration that will follow.

Co-authored-by: Huang Tao <[email protected]>
Co-authored-by: TANG Tiancheng <[email protected]>
Signed-off-by: LIU Zhiwei <[email protected]>
---
 target/riscv/cpu.h                |  8 +++
 target/riscv/cpu_bits.h           | 24 ++++++++
 target/riscv/cpu_cfg_fields.h.inc |  2 +
 target/riscv/riscv_smmpt.h        | 21 +++++++
 target/riscv/tcg/csr.c            | 99 +++++++++++++++++++++++++++++++
 5 files changed, 154 insertions(+)
 create mode 100644 target/riscv/riscv_smmpt.h

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index c9dfa7daff..8825e1c186 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -139,6 +139,7 @@ enum {
     TRANSLATE_PMP_FAIL,
     TRANSLATE_G_STAGE_FAIL,
     TRANSLATE_PMA_FAIL,
+    TRANSLATE_MPT_FAIL
 };
 
 /* Extension context status */
@@ -184,6 +185,7 @@ extern RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[];
 
 #if !defined(CONFIG_USER_ONLY)
 #include "tcg/pmp.h"
+#include "riscv_smmpt.h"
 #endif
 
 #define RV_VLEN_MAX 1024
@@ -521,6 +523,12 @@ struct CPUArchState {
     uint64_t rnmip;
     uint64_t rnmi_irqvec;
     uint64_t rnmi_excpvec;
+
+    /* Smsdid */
+    uint32_t mptmode;
+    uint32_t sdid;
+    uint64_t mptppn;
+    uint32_t msdcfg;
 #endif
 
     /* Fields from here on are preserved across CPU reset. */
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 3f146a43fe..4ed4843e3d 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -1166,4 +1166,28 @@ typedef enum CTRType {
 #define MCONTEXT64                         0x0000000000001FFFULL
 #define MCONTEXT32_HCONTEXT                0x0000007F
 #define MCONTEXT64_HCONTEXT                0x0000000000003FFFULL
+
+/* Smsdid */
+#define CSR_MMPT        0x382
+#define CSR_MSDCFG      0x74E
+
+/*
+ * MMPT register layout for MXLEN=32:
+ * MODE[31:30], 0[29:28], SDID[27:22], PPN[21:0]
+ */
+#define MMPT_MODE_MASK_32   0xC0000000
+#define MMPT_MODE_SHIFT_32  30
+#define MMPT_SDID_MASK_32   0x0FC00000
+#define MMPT_SDID_SHIFT_32  22
+#define MMPT_PPN_MASK_32    0x003FFFFF
+
+/*
+ * MMPT register layout for MXLEN=64:
+ * MODE[63:60], 0[59:58], SDID[57:52], 0[51:44], PPN[43:0]
+ */
+#define MMPT_MODE_MASK_64   0xF000000000000000ULL
+#define MMPT_MODE_SHIFT_64  60
+#define MMPT_SDID_MASK_64   0x03F0000000000000ULL
+#define MMPT_SDID_SHIFT_64  52
+#define MMPT_PPN_MASK_64    0x00000FFFFFFFFFFFULL
 #endif
diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc
index 9eb47af0a7..6b616388be 100644
--- a/target/riscv/cpu_cfg_fields.h.inc
+++ b/target/riscv/cpu_cfg_fields.h.inc
@@ -63,6 +63,8 @@ BOOL_FIELD(ext_smpmpmt)
 BOOL_FIELD(ext_svrsw60t59b)
 BOOL_FIELD(ext_svvptc)
 BOOL_FIELD(ext_svukte)
+BOOL_FIELD(ext_smmpt)
+BOOL_FIELD(ext_smsdid)
 BOOL_FIELD(ext_zdinx)
 BOOL_FIELD(ext_zaamo)
 BOOL_FIELD(ext_zacas)
diff --git a/target/riscv/riscv_smmpt.h b/target/riscv/riscv_smmpt.h
new file mode 100644
index 0000000000..74dcccf4be
--- /dev/null
+++ b/target/riscv/riscv_smmpt.h
@@ -0,0 +1,21 @@
+/*
+ * QEMU RISC-V Smmpt (Memory Protection Table)
+ *
+ * Copyright (c) 2024 Alibaba Group. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef RISCV_SMMPT_H
+#define RISCV_SMMPT_H
+
+typedef enum {
+    SMMPTBARE = 0,
+    SMMPT34   = 1,
+    SMMPT43   = 2,
+    SMMPT52   = 3,
+    SMMPT64   = 4,
+    SMMPTMAX
+} mpt_mode_t;
+
+#endif
diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
index 36f2004bc5..8ffe85caa9 100644
--- a/target/riscv/tcg/csr.c
+++ b/target/riscv/tcg/csr.c
@@ -821,6 +821,15 @@ static RISCVException rnmi(CPURISCVState *env, int csrno)
 
     return RISCV_EXCP_ILLEGAL_INST;
 }
+
+static RISCVException smsdid(CPURISCVState *env, int csrno)
+{
+    if (riscv_cpu_cfg(env)->ext_smsdid) {
+        return RISCV_EXCP_NONE;
+    }
+
+    return RISCV_EXCP_ILLEGAL_INST;
+}
 #endif
 
 static RISCVException seed(CPURISCVState *env, int csrno)
@@ -5568,6 +5577,93 @@ static RISCVException write_mnstatus(CPURISCVState *env, int csrno,
     return RISCV_EXCP_NONE;
 }
 
+static RISCVException read_mmpt(CPURISCVState *env, int csrno,
+                                target_ulong *val)
+{
+    if (riscv_cpu_xlen(env) == 32) {
+        uint32_t value = 0;
+        value |= env->mptmode << MMPT_MODE_SHIFT_32;
+        value |= (env->sdid << MMPT_SDID_SHIFT_32) & MMPT_SDID_MASK_32;
+        value |= env->mptppn & MMPT_PPN_MASK_32;
+        *val = value;
+    } else if (riscv_cpu_xlen(env) == 64) {
+        uint64_t value_64 = 0;
+        uint32_t mode_value = env->mptmode;
+        /* mpt_mode_t convert to mmpt.mode value */
+        if (mode_value) {
+            mode_value -= SMMPT43 - SMMPT34;
+        }
+        value_64 |= (uint64_t)mode_value << MMPT_MODE_SHIFT_64;
+        value_64 |= ((uint64_t)env->sdid << MMPT_SDID_SHIFT_64)
+                    & MMPT_SDID_MASK_64;
+        value_64 |= (uint64_t)env->mptppn & MMPT_PPN_MASK_64;
+        *val = value_64;
+    } else {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mmpt(CPURISCVState *env, int csrno,
+                                 target_ulong val, uintptr_t ra)
+{
+    uint32_t mode_value = 0;
+    if (!riscv_cpu_cfg(env)->ext_smmpt) {
+        goto set_remaining_fields_zero;
+    }
+
+    if (riscv_cpu_xlen(env) == 32) {
+        mode_value = (val & MMPT_MODE_MASK_32) >> MMPT_MODE_SHIFT_32;
+        /* If mode is bare, the remaining fields in mmpt must be zero */
+        if (mode_value == SMMPTBARE) {
+            goto set_remaining_fields_zero;
+        } else if (mode_value <= SMMPT34) {
+            /* Only write the legal value */
+            env->mptmode = mode_value;
+        }
+        env->sdid = (val & MMPT_SDID_MASK_32) >> MMPT_SDID_SHIFT_32;
+        env->mptppn = val & MMPT_PPN_MASK_32;
+    } else if (riscv_cpu_xlen(env) == 64) {
+        mode_value = (val & MMPT_MODE_MASK_64) >> MMPT_MODE_SHIFT_64;
+        if (mode_value == SMMPTBARE) {
+            goto set_remaining_fields_zero;
+        } else if (mode_value < SMMPTMAX) {
+            /* convert to mpt_mode_t */
+            mode_value += SMMPT43 - SMMPT34;
+            env->mptmode = mode_value;
+        }
+        env->sdid = (val & MMPT_SDID_MASK_64) >> MMPT_SDID_SHIFT_64;
+        env->mptppn = val & MMPT_PPN_MASK_64;
+        /* Smmpt64: root table PPN bits 2:0 must be zero (32KiB alignment) */
+        if (env->mptmode == SMMPT64) {
+            env->mptppn &= ~(uint64_t)0x7;
+        }
+    } else {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+    return RISCV_EXCP_NONE;
+
+set_remaining_fields_zero:
+    env->sdid = 0;
+    env->mptmode = SMMPTBARE;
+    env->mptppn = 0;
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_msdcfg(CPURISCVState *env, int csrno,
+                                   target_ulong *val)
+{
+    *val = env->msdcfg;
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_msdcfg(CPURISCVState *env, int csrno,
+                                    target_ulong val, uintptr_t ra)
+{
+    env->msdcfg = val;
+    return RISCV_EXCP_NONE;
+}
+
 #endif
 
 /* Crypto Extension */
@@ -6769,6 +6865,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
                              write_mhpmcounterh                         },
     [CSR_SCOUNTOVF]      = { "scountovf", sscofpmf,  read_scountovf,
                              .min_priv_ver = PRIV_VERSION_1_12_0 },
+    /* Supervisor Domain Identifier and Protection Registers */
+    [CSR_MMPT] =    { "mmpt",   smsdid,  read_mmpt,   write_mmpt   },
+    [CSR_MSDCFG] =  { "msdcfg", smsdid,  read_msdcfg, write_msdcfg },
 
 #endif /* !CONFIG_USER_ONLY */
 };
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.