Skip to contentSkip to conversation

RISC-V Smstateen support

PATCH Superseded Mayuresh Chitale 2 participants 11 messages Aug 1, 2022 – Aug 4, 2022 RISC-V

v7 of 11 Superseded Latest is v11 →

lore
Share & tools
lore
#0 lore raw

v7 cover RISC-V Smstateen support

This series adds support for the Smstateen specification which provides a mechanism plug potential covert channels which are opened by extensions that add to processor state that may not get context-switched. Currently access to *envcfg registers and floating point(fcsr) is controlled via smstateen.

These patches can also be found on riscv_smstateen_v7 branch at:
https://github.com/mdchitale/qemu.git

Changes in v7:
- Update smstateen check as per discussion on the following issue:
https://github.com/riscv/riscv-state-enable/issues/9
- Drop the smstateen AIA patch for now.
- Indentation and other fixes

Changes in v6:
- Sync with latest riscv-to-apply.next
- Make separate read/write ops for m/h/s/stateen1/2/3 regs
- Add check for mstateen.staten when reading or using h/s/stateen regs
- Add smstateen fcsr check for all floating point operations
- Move knobs to enable smstateen in a separate patch.

Changes in v5:
- Fix the order in which smstateen extension is added to the isa_edata_arr as
described in rule #3 the comment.

Changes in v4:
- Fix build issue with riscv32/riscv64-linux-user targets

Changes in v3:
- Fix coding style issues
- Fix *stateen0h index calculation

Changes in v2:
- Make h/s/envcfg bits in m/h/stateen registers as writeable by default.

Anup Patel (1):
target/riscv: Force disable extensions if priv spec version does not
match

Mayuresh Chitale (4):
target/riscv: Add smstateen support
target/riscv: smstateen check for h/senvcfg
target/riscv: smstateen check for fcsr
target/riscv: smstateen knobs

 roms/opensbi                              |   2 +-
 target/riscv/cpu.c                        |   2 +
 target/riscv/cpu.h                        |   4 +
 target/riscv/cpu_bits.h                   |  37 ++
 target/riscv/csr.c                        | 463 +++++++++++++++++++++-
 target/riscv/insn_trans/trans_rvf.c.inc   |  40 +-
 target/riscv/insn_trans/trans_rvzfh.c.inc |  12 +
 target/riscv/machine.c                    |  21 +
 8 files changed, 576 insertions(+), 5 deletions(-)
Signature · 1 line
2.25.1
#1 lore raw

PATCH v7 1/4 target/riscv: Add smstateen support

Smstateen extension specifies a mechanism to close the potential covert channels that could cause security issues.

This patch adds the CSRs defined in the specification and the corresponding predicates and read/write functions.

---
 target/riscv/cpu.h      |   4 +
 target/riscv/cpu_bits.h |  37 ++++
 target/riscv/csr.c      | 369 ++++++++++++++++++++++++++++++++++++++++
 target/riscv/machine.c  |  21 +++
 4 files changed, 431 insertions(+)
target/riscv/cpu.h +4 -0
index 4be4b82a83..6bff935c57 100644
@@ -354,6 +354,9 @@ struct CPUArchState {
 
     /* CSRs for execution enviornment configuration */
     uint64_t menvcfg;
+    uint64_t mstateen[SMSTATEEN_MAX_COUNT];
+    uint64_t hstateen[SMSTATEEN_MAX_COUNT];
+    uint64_t sstateen[SMSTATEEN_MAX_COUNT];
     target_ulong senvcfg;
     uint64_t henvcfg;
 #endif
@@ -427,6 +430,7 @@ struct RISCVCPUConfig {
     bool ext_ifencei;
     bool ext_icsr;
     bool ext_zihintpause;
+    bool ext_smstateen;
     bool ext_svinval;
     bool ext_svnapot;
     bool ext_svpbmt;
target/riscv/cpu_bits.h +37 -0
index 6be5a9e9f0..c773e0d310 100644
@@ -199,6 +199,12 @@
 /* Supervisor Configuration CSRs */
 #define CSR_SENVCFG         0x10A
 
+/* Supervisor state CSRs */
+#define CSR_SSTATEEN0       0x10C
+#define CSR_SSTATEEN1       0x10D
+#define CSR_SSTATEEN2       0x10E
+#define CSR_SSTATEEN3       0x10F
+
 /* Supervisor Trap Handling */
 #define CSR_SSCRATCH        0x140
 #define CSR_SEPC            0x141
@@ -242,6 +248,16 @@
 #define CSR_HENVCFG         0x60A
 #define CSR_HENVCFGH        0x61A
 
+/* Hypervisor state CSRs */
+#define CSR_HSTATEEN0       0x60C
+#define CSR_HSTATEEN0H      0x61C
+#define CSR_HSTATEEN1       0x60D
+#define CSR_HSTATEEN1H      0x61D
+#define CSR_HSTATEEN2       0x60E
+#define CSR_HSTATEEN2H      0x61E
+#define CSR_HSTATEEN3       0x60F
+#define CSR_HSTATEEN3H      0x61F
+
 /* Virtual CSRs */
 #define CSR_VSSTATUS        0x200
 #define CSR_VSIE            0x204
@@ -283,6 +299,27 @@
 #define CSR_MENVCFG         0x30A
 #define CSR_MENVCFGH        0x31A
 
+/* Machine state CSRs */
+#define CSR_MSTATEEN0       0x30C
+#define CSR_MSTATEEN0H      0x31C
+#define CSR_MSTATEEN1       0x30D
+#define CSR_MSTATEEN1H      0x31D
+#define CSR_MSTATEEN2       0x30E
+#define CSR_MSTATEEN2H      0x31E
+#define CSR_MSTATEEN3       0x30F
+#define CSR_MSTATEEN3H      0x31F
+
+/* Common defines for all smstateen */
+#define SMSTATEEN_MAX_COUNT 4
+#define SMSTATEEN0_CS       (1ULL << 0)
+#define SMSTATEEN0_FCSR     (1ULL << 1)
+#define SMSTATEEN0_HSCONTXT (1ULL << 57)
+#define SMSTATEEN0_IMSIC    (1ULL << 58)
+#define SMSTATEEN0_AIA      (1ULL << 59)
+#define SMSTATEEN0_SVSLCT   (1ULL << 60)
+#define SMSTATEEN0_HSENVCFG (1ULL << 62)
+#define SMSTATEEN_STATEEN   (1ULL << 63)
+
 /* Enhanced Physical Memory Protection (ePMP) */
 #define CSR_MSECCFG         0x747
 #define CSR_MSECCFGH        0x757
target/riscv/csr.c +369 -0

387 lines not on this page · raw message

target/riscv/machine.c +21 -0
index dc182ca811..ef418ac19d 100644
@@ -262,6 +262,26 @@ static int riscv_cpu_post_load(void *opaque, int version_id)
     return 0;
 }
 
+static bool smstateen_needed(void *opaque)
+{
+    RISCVCPU *cpu = opaque;
+
+    return cpu->cfg.ext_smstateen;
+}
+
+static const VMStateDescription vmstate_smstateen = {
+    .name = "cpu/smtateen",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = smstateen_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64_ARRAY(env.mstateen, RISCVCPU, 4),
+        VMSTATE_UINT64_ARRAY(env.hstateen, RISCVCPU, 4),
+        VMSTATE_UINT64_ARRAY(env.sstateen, RISCVCPU, 4),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static bool envcfg_needed(void *opaque)
 {
     RISCVCPU *cpu = opaque;
@@ -372,6 +392,7 @@ const VMStateDescription vmstate_riscv_cpu = {
         &vmstate_kvmtimer,
         &vmstate_envcfg,
         &vmstate_debug,
+        &vmstate_smstateen,
         NULL
     }
 };
Signature · 1 line
2.25.1
#2 lore raw

Re: [PATCH v7 1/4] target/riscv: Add smstateen support

Quoted 121 lines · Mayuresh Chitale

Smstateen extension specifies a mechanism to close the potential covert channels that could cause security issues.

This patch adds the CSRs defined in the specification and the corresponding predicates and read/write functions.

---
  target/riscv/cpu.h      |   4 +
  target/riscv/cpu_bits.h |  37 ++++
  target/riscv/csr.c      | 369 ++++++++++++++++++++++++++++++++++++++++
  target/riscv/machine.c  |  21 +++
  4 files changed, 431 insertions(+)
target/riscv/cpu.h +4 -0
index 4be4b82a83..6bff935c57 100644
@@ -354,6 +354,9 @@ struct CPUArchState {
 
      /* CSRs for execution enviornment configuration */
      uint64_t menvcfg;
+    uint64_t mstateen[SMSTATEEN_MAX_COUNT];
+    uint64_t hstateen[SMSTATEEN_MAX_COUNT];
+    uint64_t sstateen[SMSTATEEN_MAX_COUNT];
      target_ulong senvcfg;
      uint64_t henvcfg;
  #endif
@@ -427,6 +430,7 @@ struct RISCVCPUConfig {
      bool ext_ifencei;
      bool ext_icsr;
      bool ext_zihintpause;
+    bool ext_smstateen;
      bool ext_svinval;
      bool ext_svnapot;
      bool ext_svpbmt;
target/riscv/cpu_bits.h +37 -0
index 6be5a9e9f0..c773e0d310 100644
@@ -199,6 +199,12 @@
  /* Supervisor Configuration CSRs */
  #define CSR_SENVCFG         0x10A
 
+/* Supervisor state CSRs */
+#define CSR_SSTATEEN0       0x10C
+#define CSR_SSTATEEN1       0x10D
+#define CSR_SSTATEEN2       0x10E
+#define CSR_SSTATEEN3       0x10F
+
  /* Supervisor Trap Handling */
  #define CSR_SSCRATCH        0x140
  #define CSR_SEPC            0x141
@@ -242,6 +248,16 @@
  #define CSR_HENVCFG         0x60A
  #define CSR_HENVCFGH        0x61A
 
+/* Hypervisor state CSRs */
+#define CSR_HSTATEEN0       0x60C
+#define CSR_HSTATEEN0H      0x61C
+#define CSR_HSTATEEN1       0x60D
+#define CSR_HSTATEEN1H      0x61D
+#define CSR_HSTATEEN2       0x60E
+#define CSR_HSTATEEN2H      0x61E
+#define CSR_HSTATEEN3       0x60F
+#define CSR_HSTATEEN3H      0x61F
+
  /* Virtual CSRs */
  #define CSR_VSSTATUS        0x200
  #define CSR_VSIE            0x204
@@ -283,6 +299,27 @@
  #define CSR_MENVCFG         0x30A
  #define CSR_MENVCFGH        0x31A
 
+/* Machine state CSRs */
+#define CSR_MSTATEEN0       0x30C
+#define CSR_MSTATEEN0H      0x31C
+#define CSR_MSTATEEN1       0x30D
+#define CSR_MSTATEEN1H      0x31D
+#define CSR_MSTATEEN2       0x30E
+#define CSR_MSTATEEN2H      0x31E
+#define CSR_MSTATEEN3       0x30F
+#define CSR_MSTATEEN3H      0x31F
+
+/* Common defines for all smstateen */
+#define SMSTATEEN_MAX_COUNT 4
+#define SMSTATEEN0_CS       (1ULL << 0)
+#define SMSTATEEN0_FCSR     (1ULL << 1)
+#define SMSTATEEN0_HSCONTXT (1ULL << 57)
+#define SMSTATEEN0_IMSIC    (1ULL << 58)
+#define SMSTATEEN0_AIA      (1ULL << 59)
+#define SMSTATEEN0_SVSLCT   (1ULL << 60)
+#define SMSTATEEN0_HSENVCFG (1ULL << 62)
+#define SMSTATEEN_STATEEN   (1ULL << 63)
+
  /* Enhanced Physical Memory Protection (ePMP) */
  #define CSR_MSECCFG         0x747
  #define CSR_MSECCFGH        0x757
target/riscv/csr.c +15 -0
index 0fb042b2fd..ad1642fb9b 100644
@@ -346,6 +346,68 @@ static RISCVException umode32(CPURISCVState *env, int csrno)
      return umode(env, csrno);
  }
 
+static RISCVException mstateen(CPURISCVState *env, int csrno)
+{
+    CPUState *cs = env_cpu(env);
+    RISCVCPU *cpu = RISCV_CPU(cs);
+
+    if (!cpu->cfg.ext_smstateen) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+
+    return any(env, csrno);
+}
+
+static RISCVException hstateen_pred(CPURISCVState *env, int csrno, int base)
+{
+    CPUState *cs = env_cpu(env);

target/riscv/csr.c static RISCVException umode32(CPURISCVState *env, int csrno) · line 373

Quoted 10 lines
target/riscv/csr.c +10 -0
+    RISCVCPU *cpu = RISCV_CPU(cs);
+
+    if (!cpu->cfg.ext_smstateen) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+
+    if (!(env->mstateen[csrno - base] & SMSTATEEN_STATEEN)) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+

mstateen only control the access from less-privilege levels.  If the access is from M mode, it will always

be allowed.  So I think we should add check for current priv  is less than M mode here.

Similar to sstateen.

Regards,

Weiwei Li

Quoted 400 lines
target/riscv/csr.c +344 -0
+    return hmode(env, csrno);
+}
+
+static RISCVException hstateen(CPURISCVState *env, int csrno)
+{
+    return hstateen_pred(env, csrno, CSR_HSTATEEN0);
+}
+
+static RISCVException hstateenh(CPURISCVState *env, int csrno)
+{
+    return hstateen_pred(env, csrno, CSR_HSTATEEN0H);
+}
+
+static RISCVException sstateen(CPURISCVState *env, int csrno)
+{
+    bool virt = riscv_cpu_virt_enabled(env);
+    int index = csrno - CSR_SSTATEEN0;
+    CPUState *cs = env_cpu(env);
+    RISCVCPU *cpu = RISCV_CPU(cs);
+
+    if (!cpu->cfg.ext_smstateen) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+
+    if (!(env->mstateen[index] & SMSTATEEN_STATEEN)) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+
+    if (virt) {
+        if (!(env->hstateen[index] & SMSTATEEN_STATEEN)) {
+            return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+        }
+    }
+
+    return smode(env, csrno);
+}
+
  /* Checks if PointerMasking registers could be accessed */
  static RISCVException pointer_masking(CPURISCVState *env, int csrno)
  {
@@ -1706,6 +1768,263 @@ static RISCVException write_henvcfgh(CPURISCVState *env, int csrno,
      return RISCV_EXCP_NONE;
  }
 
+static inline void write_smstateen(CPURISCVState *env, uint64_t *reg,
+                                   uint64_t wr_mask, uint64_t new_val)
+{
+    *reg = (*reg & ~wr_mask) | (new_val & wr_mask);
+}
+
+static RISCVException read_mstateen(CPURISCVState *env, int csrno,
+                                    target_ulong *val)
+{
+    *val = env->mstateen[csrno - CSR_MSTATEEN0];
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mstateen(CPURISCVState *env, int csrno,
+                                     uint64_t wr_mask, target_ulong new_val)
+{
+    uint64_t *reg;
+
+    reg = &env->mstateen[csrno - CSR_MSTATEEN0];
+    write_smstateen(env, reg, wr_mask, new_val);
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mstateen0(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    uint64_t wr_mask = SMSTATEEN_STATEEN;
+
+    return write_mstateen(env, csrno, wr_mask, new_val);
+}
+
+static RISCVException write_mstateen1(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    return write_mstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_mstateen2(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    return write_mstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_mstateen3(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    return write_mstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException read_mstateenh(CPURISCVState *env, int csrno,
+                                      target_ulong *val)
+{
+    *val = env->mstateen[csrno - CSR_MSTATEEN0H] >> 32;
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mstateenh(CPURISCVState *env, int csrno,
+                                      uint64_t wr_mask, target_ulong new_val)
+{
+    uint64_t *reg, val;
+
+    reg = &env->mstateen[csrno - CSR_MSTATEEN0H];
+    val = (uint64_t)new_val << 32;
+    val |= *reg & 0xFFFFFFFF;
+    write_smstateen(env, reg, wr_mask, val);
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mstateen0h(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    uint64_t wr_mask = SMSTATEEN_STATEEN;
+
+    return write_mstateenh(env, csrno, wr_mask, new_val);
+}
+
+static RISCVException write_mstateen1h(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    return write_mstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_mstateen2h(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    return write_mstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_mstateen3h(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    return write_mstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException read_hstateen(CPURISCVState *env, int csrno,
+                                    target_ulong *val)
+{
+    int index = csrno - CSR_HSTATEEN0;
+
+    *val = env->hstateen[index] & env->mstateen[index];
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_hstateen(CPURISCVState *env, int csrno,
+                                     uint64_t mask, target_ulong new_val)
+{
+    int index = csrno - CSR_HSTATEEN0;
+    uint64_t *reg, wr_mask;
+
+    reg = &env->hstateen[index];
+    wr_mask = env->mstateen[index] & mask;
+    write_smstateen(env, reg, wr_mask, new_val);
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_hstateen0(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    uint64_t wr_mask = SMSTATEEN_STATEEN;
+
+    return write_hstateen(env, csrno, wr_mask, new_val);
+}
+
+static RISCVException write_hstateen1(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    return write_hstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_hstateen2(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    return write_hstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_hstateen3(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    return write_hstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException read_hstateenh(CPURISCVState *env, int csrno,
+                                     target_ulong *val)
+{
+    int index = csrno - CSR_HSTATEEN0H;
+
+    *val = (env->hstateen[index] >> 32) & (env->mstateen[index] >> 32);
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_hstateenh(CPURISCVState *env, int csrno,
+                                      uint64_t mask, target_ulong new_val)
+{
+    int index = csrno - CSR_HSTATEEN0H;
+    uint64_t *reg, wr_mask, val;
+
+    reg = &env->hstateen[index];
+    val = (uint64_t)new_val << 32;
+    val |= *reg & 0xFFFFFFFF;
+    wr_mask = env->mstateen[index] & mask;
+    write_smstateen(env, reg, wr_mask, val);
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_hstateen0h(CPURISCVState *env, int csrno,
+                                       target_ulong new_val)
+{
+    uint64_t wr_mask = SMSTATEEN_STATEEN;
+
+    return write_hstateenh(env, csrno, wr_mask, new_val);
+}
+
+static RISCVException write_hstateen1h(CPURISCVState *env, int csrno,
+                                       target_ulong new_val)
+{
+    return write_hstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_hstateen2h(CPURISCVState *env, int csrno,
+                                       target_ulong new_val)
+{
+    return write_hstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_hstateen3h(CPURISCVState *env, int csrno,
+                                       target_ulong new_val)
+{
+    return write_hstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException read_sstateen(CPURISCVState *env, int csrno,
+                                    target_ulong *val)
+{
+    bool virt = riscv_cpu_virt_enabled(env);
+    int index = csrno - CSR_SSTATEEN0;
+
+    *val = env->sstateen[index] & env->mstateen[index];
+    if (virt) {
+        *val &= env->hstateen[index];
+    }
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_sstateen(CPURISCVState *env, int csrno,
+                                     uint64_t mask, target_ulong new_val)
+{
+    bool virt = riscv_cpu_virt_enabled(env);
+    int index = csrno - CSR_SSTATEEN0;
+    uint64_t wr_mask;
+    uint64_t *reg;
+
+    wr_mask = env->mstateen[index] & mask;
+    if (virt) {
+        wr_mask &= env->hstateen[index];
+    }
+
+    reg = &env->sstateen[index];
+    write_smstateen(env, reg, wr_mask, new_val);
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_sstateen0(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    uint64_t wr_mask = SMSTATEEN_STATEEN;
+
+    return write_sstateen(env, csrno, wr_mask, new_val);
+}
+
+static RISCVException write_sstateen1(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    return write_sstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_sstateen2(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    return write_sstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_sstateen3(CPURISCVState *env, int csrno,
+                                      target_ulong new_val)
+{
+    return write_sstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
  static RISCVException rmw_mip64(CPURISCVState *env, int csrno,
                                  uint64_t *ret_val,
                                  uint64_t new_val, uint64_t wr_mask)
@@ -3569,6 +3888,56 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
      [CSR_HENVCFGH] = { "henvcfgh", hmode32, read_henvcfgh, write_henvcfgh,
                         .min_priv_ver = PRIV_VERSION_1_12_0              },
 
+    /* Smstateen extension CSRs */
+    [CSR_MSTATEEN0] = { "mstateen0", mstateen, read_mstateen, write_mstateen0,
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN0H] = { "mstateen0h", mstateen, read_mstateenh,
+                          write_mstateen0h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN1] = { "mstateen1", mstateen, read_mstateen, write_mstateen1,
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN1H] = { "mstateen1h", mstateen, read_mstateenh,
+                          write_mstateen1h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN2] = { "mstateen2", mstateen, read_mstateen, write_mstateen2,
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN2H] = { "mstateen2h", mstateen, read_mstateenh,
+                          write_mstateen2h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN3] = { "mstateen3", mstateen, read_mstateen, write_mstateen3,
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN3H] = { "mstateen3h", mstateen, read_mstateenh,
+                          write_mstateen3h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN0] = { "hstateen0", hstateen, read_hstateen, write_hstateen0,
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN0H] = { "hstateen0h", hstateenh, read_hstateenh,
+                          write_hstateen0h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN1] = { "hstateen1", hstateen, read_hstateen, write_hstateen1,
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN1H] = { "hstateen1h", hstateenh, read_hstateenh,
+                          write_hstateen1h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN2] = { "hstateen2", hstateen, read_hstateen, write_hstateen2,
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN2H] = { "hstateen2h", hstateenh, read_hstateenh,
+                          write_hstateen2h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN3] = { "hstateen3", hstateen, read_hstateen, write_hstateen3,
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN3H] = { "hstateen3h", hstateenh, read_hstateenh,
+                          write_hstateen3h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_SSTATEEN0] = { "sstateen0", sstateen, read_sstateen, write_sstateen0,
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_SSTATEEN1] = { "sstateen1", sstateen, read_sstateen, write_sstateen1,
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_SSTATEEN2] = { "sstateen2", sstateen, read_sstateen, write_sstateen2,
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_SSTATEEN3] = { "sstateen3", sstateen, read_sstateen, write_sstateen3,
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+
      /* Supervisor Trap Setup */
      [CSR_SSTATUS]    = { "sstatus",    smode, read_sstatus,    write_sstatus,
                           NULL,                read_sstatus_i128               },
target/riscv/machine.c +21 -0
index dc182ca811..ef418ac19d 100644
@@ -262,6 +262,26 @@ static int riscv_cpu_post_load(void *opaque, int version_id)
      return 0;
  }
 
+static bool smstateen_needed(void *opaque)
+{
+    RISCVCPU *cpu = opaque;
+
+    return cpu->cfg.ext_smstateen;
+}
+
+static const VMStateDescription vmstate_smstateen = {
+    .name = "cpu/smtateen",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = smstateen_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64_ARRAY(env.mstateen, RISCVCPU, 4),
+        VMSTATE_UINT64_ARRAY(env.hstateen, RISCVCPU, 4),
+        VMSTATE_UINT64_ARRAY(env.sstateen, RISCVCPU, 4),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
  static bool envcfg_needed(void *opaque)
  {
      RISCVCPU *cpu = opaque;
@@ -372,6 +392,7 @@ const VMStateDescription vmstate_riscv_cpu = {
          &vmstate_kvmtimer,
          &vmstate_envcfg,
          &vmstate_debug,
+        &vmstate_smstateen,
          NULL
      }
  };
#3 lore raw

Re: [PATCH v7 1/4] target/riscv: Add smstateen support

Quoted 139 lines · Weiwei Li
Quoted 124 lines · Mayuresh Chitale

Smstateen extension specifies a mechanism to close the potential covert channels that could cause security issues.

This patch adds the CSRs defined in the specification and the corresponding predicates and read/write functions.

---
  target/riscv/cpu.h      |   4 +
  target/riscv/cpu_bits.h |  37 ++++
  target/riscv/csr.c      | 369
++++++++++++++++++++++++++++++++++++++++
  target/riscv/machine.c  |  21 +++
  4 files changed, 431 insertions(+)
target/riscv/cpu.h +4 -0
index 4be4b82a83..6bff935c57 100644
@@ -354,6 +354,9 @@ struct CPUArchState {
 
      /* CSRs for execution enviornment configuration */
      uint64_t menvcfg;
+    uint64_t mstateen[SMSTATEEN_MAX_COUNT];
+    uint64_t hstateen[SMSTATEEN_MAX_COUNT];
+    uint64_t sstateen[SMSTATEEN_MAX_COUNT];
      target_ulong senvcfg;
      uint64_t henvcfg;
  #endif
@@ -427,6 +430,7 @@ struct RISCVCPUConfig {
      bool ext_ifencei;
      bool ext_icsr;
      bool ext_zihintpause;
+    bool ext_smstateen;
      bool ext_svinval;
      bool ext_svnapot;
      bool ext_svpbmt;
target/riscv/cpu_bits.h +37 -0
index 6be5a9e9f0..c773e0d310 100644
@@ -199,6 +199,12 @@
  /* Supervisor Configuration CSRs */
  #define CSR_SENVCFG         0x10A
 
+/* Supervisor state CSRs */
+#define CSR_SSTATEEN0       0x10C
+#define CSR_SSTATEEN1       0x10D
+#define CSR_SSTATEEN2       0x10E
+#define CSR_SSTATEEN3       0x10F
+
  /* Supervisor Trap Handling */
  #define CSR_SSCRATCH        0x140
  #define CSR_SEPC            0x141
@@ -242,6 +248,16 @@
  #define CSR_HENVCFG         0x60A
  #define CSR_HENVCFGH        0x61A
 
+/* Hypervisor state CSRs */
+#define CSR_HSTATEEN0       0x60C
+#define CSR_HSTATEEN0H      0x61C
+#define CSR_HSTATEEN1       0x60D
+#define CSR_HSTATEEN1H      0x61D
+#define CSR_HSTATEEN2       0x60E
+#define CSR_HSTATEEN2H      0x61E
+#define CSR_HSTATEEN3       0x60F
+#define CSR_HSTATEEN3H      0x61F
+
  /* Virtual CSRs */
  #define CSR_VSSTATUS        0x200
  #define CSR_VSIE            0x204
@@ -283,6 +299,27 @@
  #define CSR_MENVCFG         0x30A
  #define CSR_MENVCFGH        0x31A
 
+/* Machine state CSRs */
+#define CSR_MSTATEEN0       0x30C
+#define CSR_MSTATEEN0H      0x31C
+#define CSR_MSTATEEN1       0x30D
+#define CSR_MSTATEEN1H      0x31D
+#define CSR_MSTATEEN2       0x30E
+#define CSR_MSTATEEN2H      0x31E
+#define CSR_MSTATEEN3       0x30F
+#define CSR_MSTATEEN3H      0x31F
+
+/* Common defines for all smstateen */
+#define SMSTATEEN_MAX_COUNT 4
+#define SMSTATEEN0_CS       (1ULL << 0)
+#define SMSTATEEN0_FCSR     (1ULL << 1)
+#define SMSTATEEN0_HSCONTXT (1ULL << 57)
+#define SMSTATEEN0_IMSIC    (1ULL << 58)
+#define SMSTATEEN0_AIA      (1ULL << 59)
+#define SMSTATEEN0_SVSLCT   (1ULL << 60)
+#define SMSTATEEN0_HSENVCFG (1ULL << 62)
+#define SMSTATEEN_STATEEN   (1ULL << 63)
+
  /* Enhanced Physical Memory Protection (ePMP) */
  #define CSR_MSECCFG         0x747
  #define CSR_MSECCFGH        0x757
target/riscv/csr.c +15 -0
index 0fb042b2fd..ad1642fb9b 100644
@@ -346,6 +346,68 @@ static RISCVException umode32(CPURISCVState
 *env, int csrno)
      return umode(env, csrno);
  }
 
+static RISCVException mstateen(CPURISCVState *env, int csrno)
+{
+    CPUState *cs = env_cpu(env);
+    RISCVCPU *cpu = RISCV_CPU(cs);
+
+    if (!cpu->cfg.ext_smstateen) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+
+    return any(env, csrno);
+}
+
+static RISCVException hstateen_pred(CPURISCVState *env, int csrno,
 int base)
+{
+    CPUState *cs = env_cpu(env);

target/riscv/csr.c static RISCVException umode32(CPURISCVState · line 375

Quoted 10 lines
target/riscv/csr.c +10 -0
+    RISCVCPU *cpu = RISCV_CPU(cs);
+
+    if (!cpu->cfg.ext_smstateen) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+
+    if (!(env->mstateen[csrno - base] & SMSTATEEN_STATEEN)) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+

mstateen only control the access from less-privilege levels. If the access is from M mode, it will always

Quoted 5 lines

be allowed. So I think we should add check for current priv is less
than M mode here.

Similar to sstateen.

Ok. I will fix in the next version.

Quoted 467 lines

Regards,

Weiwei Li

Quoted 462 lines
target/riscv/csr.c +37 -0
+    return hmode(env, csrno);
+}
+
+static RISCVException hstateen(CPURISCVState *env, int csrno)
+{
+    return hstateen_pred(env, csrno, CSR_HSTATEEN0);
+}
+
+static RISCVException hstateenh(CPURISCVState *env, int csrno)
+{
+    return hstateen_pred(env, csrno, CSR_HSTATEEN0H);
+}
+
+static RISCVException sstateen(CPURISCVState *env, int csrno)
+{
+    bool virt = riscv_cpu_virt_enabled(env);
+    int index = csrno - CSR_SSTATEEN0;
+    CPUState *cs = env_cpu(env);
+    RISCVCPU *cpu = RISCV_CPU(cs);
+
+    if (!cpu->cfg.ext_smstateen) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+
+    if (!(env->mstateen[index] & SMSTATEEN_STATEEN)) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+
+    if (virt) {
+        if (!(env->hstateen[index] & SMSTATEEN_STATEEN)) {
+            return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+        }
+    }
+
+    return smode(env, csrno);
+}
+
  /* Checks if PointerMasking registers could be accessed */

static RISCVException pointer_masking(CPURISCVState *env, int
csrno)
{

target/riscv/csr.c +15 -0
@@ -1706,6 +1768,263 @@ static RISCVException
 write_henvcfgh(CPURISCVState *env, int csrno,
      return RISCV_EXCP_NONE;
  }
 
+static inline void write_smstateen(CPURISCVState *env, uint64_t
 *reg,
+                                   uint64_t wr_mask, uint64_t
 new_val)
+{
+    *reg = (*reg & ~wr_mask) | (new_val & wr_mask);
+}
+
+static RISCVException read_mstateen(CPURISCVState *env, int csrno,
+                                    target_ulong *val)
+{
+    *val = env->mstateen[csrno - CSR_MSTATEEN0];
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mstateen(CPURISCVState *env, int

csrno,
+ uint64_t wr_mask,
target_ulong new_val)

target/riscv/csr.c +10 -0
+{
+    uint64_t *reg;
+
+    reg = &env->mstateen[csrno - CSR_MSTATEEN0];
+    write_smstateen(env, reg, wr_mask, new_val);
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mstateen0(CPURISCVState *env, int

csrno,

target/riscv/csr.c +8 -0
+                                      target_ulong new_val)
+{
+    uint64_t wr_mask = SMSTATEEN_STATEEN;
+
+    return write_mstateen(env, csrno, wr_mask, new_val);
+}
+
+static RISCVException write_mstateen1(CPURISCVState *env, int

csrno,

target/riscv/csr.c +6 -0
+                                      target_ulong new_val)
+{
+    return write_mstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_mstateen2(CPURISCVState *env, int

csrno,

target/riscv/csr.c +6 -0
+                                      target_ulong new_val)
+{
+    return write_mstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_mstateen3(CPURISCVState *env, int

csrno,

target/riscv/csr.c +6 -0
+                                      target_ulong new_val)
+{
+    return write_mstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException read_mstateenh(CPURISCVState *env, int

csrno,

target/riscv/csr.c +8 -0
+                                      target_ulong *val)
+{
+    *val = env->mstateen[csrno - CSR_MSTATEEN0H] >> 32;
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mstateenh(CPURISCVState *env, int

csrno,
+ uint64_t wr_mask,
target_ulong new_val)

target/riscv/csr.c +12 -0
+{
+    uint64_t *reg, val;
+
+    reg = &env->mstateen[csrno - CSR_MSTATEEN0H];
+    val = (uint64_t)new_val << 32;
+    val |= *reg & 0xFFFFFFFF;
+    write_smstateen(env, reg, wr_mask, val);
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mstateen0h(CPURISCVState *env, int

csrno,

target/riscv/csr.c +8 -0
+                                      target_ulong new_val)
+{
+    uint64_t wr_mask = SMSTATEEN_STATEEN;
+
+    return write_mstateenh(env, csrno, wr_mask, new_val);
+}
+
+static RISCVException write_mstateen1h(CPURISCVState *env, int

csrno,

target/riscv/csr.c +3 -0
+                                      target_ulong new_val)
+{
+    return write_mstateenh(env, csrno, SMSTATEEN_STATEEN,

new_val);

target/riscv/csr.c +3 -0
+}
+
+static RISCVException write_mstateen2h(CPURISCVState *env, int

csrno,

target/riscv/csr.c +3 -0
+                                      target_ulong new_val)
+{
+    return write_mstateenh(env, csrno, SMSTATEEN_STATEEN,

new_val);

target/riscv/csr.c +3 -0
+}
+
+static RISCVException write_mstateen3h(CPURISCVState *env, int

csrno,

target/riscv/csr.c +3 -0
+                                      target_ulong new_val)
+{
+    return write_mstateenh(env, csrno, SMSTATEEN_STATEEN,

new_val);

target/riscv/csr.c +13 -0
+}
+
+static RISCVException read_hstateen(CPURISCVState *env, int csrno,
+                                    target_ulong *val)
+{
+    int index = csrno - CSR_HSTATEEN0;
+
+    *val = env->hstateen[index] & env->mstateen[index];
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_hstateen(CPURISCVState *env, int

csrno,
+ uint64_t mask, target_ulong
new_val)

target/riscv/csr.c +12 -0
+{
+    int index = csrno - CSR_HSTATEEN0;
+    uint64_t *reg, wr_mask;
+
+    reg = &env->hstateen[index];
+    wr_mask = env->mstateen[index] & mask;
+    write_smstateen(env, reg, wr_mask, new_val);
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_hstateen0(CPURISCVState *env, int

csrno,

target/riscv/csr.c +8 -0
+                                      target_ulong new_val)
+{
+    uint64_t wr_mask = SMSTATEEN_STATEEN;
+
+    return write_hstateen(env, csrno, wr_mask, new_val);
+}
+
+static RISCVException write_hstateen1(CPURISCVState *env, int

csrno,

target/riscv/csr.c +6 -0
+                                      target_ulong new_val)
+{
+    return write_hstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_hstateen2(CPURISCVState *env, int

csrno,

target/riscv/csr.c +6 -0
+                                      target_ulong new_val)
+{
+    return write_hstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_hstateen3(CPURISCVState *env, int

csrno,

target/riscv/csr.c +6 -0
+                                      target_ulong new_val)
+{
+    return write_hstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException read_hstateenh(CPURISCVState *env, int

csrno,

target/riscv/csr.c +5 -0
+                                     target_ulong *val)
+{
+    int index = csrno - CSR_HSTATEEN0H;
+
+    *val = (env->hstateen[index] >> 32) & (env->mstateen[index] >>

32);

target/riscv/csr.c +5 -0
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_hstateenh(CPURISCVState *env, int

csrno,
+ uint64_t mask, target_ulong
new_val)

target/riscv/csr.c +14 -0
+{
+    int index = csrno - CSR_HSTATEEN0H;
+    uint64_t *reg, wr_mask, val;
+
+    reg = &env->hstateen[index];
+    val = (uint64_t)new_val << 32;
+    val |= *reg & 0xFFFFFFFF;
+    wr_mask = env->mstateen[index] & mask;
+    write_smstateen(env, reg, wr_mask, val);
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_hstateen0h(CPURISCVState *env, int

csrno,

target/riscv/csr.c +8 -0
+                                       target_ulong new_val)
+{
+    uint64_t wr_mask = SMSTATEEN_STATEEN;
+
+    return write_hstateenh(env, csrno, wr_mask, new_val);
+}
+
+static RISCVException write_hstateen1h(CPURISCVState *env, int

csrno,

target/riscv/csr.c +3 -0
+                                       target_ulong new_val)
+{
+    return write_hstateenh(env, csrno, SMSTATEEN_STATEEN,

new_val);

target/riscv/csr.c +3 -0
+}
+
+static RISCVException write_hstateen2h(CPURISCVState *env, int

csrno,

target/riscv/csr.c +3 -0
+                                       target_ulong new_val)
+{
+    return write_hstateenh(env, csrno, SMSTATEEN_STATEEN,

new_val);

target/riscv/csr.c +3 -0
+}
+
+static RISCVException write_hstateen3h(CPURISCVState *env, int

csrno,

target/riscv/csr.c +3 -0
+                                       target_ulong new_val)
+{
+    return write_hstateenh(env, csrno, SMSTATEEN_STATEEN,

new_val);

target/riscv/csr.c +17 -0
+}
+
+static RISCVException read_sstateen(CPURISCVState *env, int csrno,
+                                    target_ulong *val)
+{
+    bool virt = riscv_cpu_virt_enabled(env);
+    int index = csrno - CSR_SSTATEEN0;
+
+    *val = env->sstateen[index] & env->mstateen[index];
+    if (virt) {
+        *val &= env->hstateen[index];
+    }
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_sstateen(CPURISCVState *env, int

csrno,
+ uint64_t mask, target_ulong
new_val)

target/riscv/csr.c +18 -0
+{
+    bool virt = riscv_cpu_virt_enabled(env);
+    int index = csrno - CSR_SSTATEEN0;
+    uint64_t wr_mask;
+    uint64_t *reg;
+
+    wr_mask = env->mstateen[index] & mask;
+    if (virt) {
+        wr_mask &= env->hstateen[index];
+    }
+
+    reg = &env->sstateen[index];
+    write_smstateen(env, reg, wr_mask, new_val);
+
+    return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_sstateen0(CPURISCVState *env, int

csrno,

target/riscv/csr.c +8 -0
+                                      target_ulong new_val)
+{
+    uint64_t wr_mask = SMSTATEEN_STATEEN;
+
+    return write_sstateen(env, csrno, wr_mask, new_val);
+}
+
+static RISCVException write_sstateen1(CPURISCVState *env, int

csrno,

target/riscv/csr.c +6 -0
+                                      target_ulong new_val)
+{
+    return write_sstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_sstateen2(CPURISCVState *env, int

csrno,

target/riscv/csr.c +6 -0
+                                      target_ulong new_val)
+{
+    return write_sstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
+static RISCVException write_sstateen3(CPURISCVState *env, int

csrno,

target/riscv/csr.c +5 -0
+                                      target_ulong new_val)
+{
+    return write_sstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
+}
+
  static RISCVException rmw_mip64(CPURISCVState *env, int csrno,
                                  uint64_t *ret_val,
                                  uint64_t new_val, uint64_t

wr_mask)

target/riscv/csr.c +2 -0
@@ -3569,6 +3888,56 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE]
 = {
      [CSR_HENVCFGH] = { "henvcfgh", hmode32, read_henvcfgh,
 write_henvcfgh,
                         .min_priv_ver =
 PRIV_VERSION_1_12_0              },
 
+    /* Smstateen extension CSRs */
+    [CSR_MSTATEEN0] = { "mstateen0", mstateen, read_mstateen,

write_mstateen0,

target/riscv/csr.c +5 -0
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN0H] = { "mstateen0h", mstateen, read_mstateenh,
+                          write_mstateen0h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN1] = { "mstateen1", mstateen, read_mstateen,

write_mstateen1,

target/riscv/csr.c +5 -0
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN1H] = { "mstateen1h", mstateen, read_mstateenh,
+                          write_mstateen1h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN2] = { "mstateen2", mstateen, read_mstateen,

write_mstateen2,

target/riscv/csr.c +5 -0
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN2H] = { "mstateen2h", mstateen, read_mstateenh,
+                          write_mstateen2h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN3] = { "mstateen3", mstateen, read_mstateen,

write_mstateen3,

target/riscv/csr.c +5 -0
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_MSTATEEN3H] = { "mstateen3h", mstateen, read_mstateenh,
+                          write_mstateen3h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN0] = { "hstateen0", hstateen, read_hstateen,

write_hstateen0,

target/riscv/csr.c +5 -0
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN0H] = { "hstateen0h", hstateenh, read_hstateenh,
+                          write_hstateen0h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN1] = { "hstateen1", hstateen, read_hstateen,

write_hstateen1,

target/riscv/csr.c +5 -0
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN1H] = { "hstateen1h", hstateenh, read_hstateenh,
+                          write_hstateen1h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN2] = { "hstateen2", hstateen, read_hstateen,

write_hstateen2,

target/riscv/csr.c +5 -0
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN2H] = { "hstateen2h", hstateenh, read_hstateenh,
+                          write_hstateen2h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN3] = { "hstateen3", hstateen, read_hstateen,

write_hstateen3,

target/riscv/csr.c +5 -0
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_HSTATEEN3H] = { "hstateen3h", hstateenh, read_hstateenh,
+                          write_hstateen3h,
+                         .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_SSTATEEN0] = { "sstateen0", sstateen, read_sstateen,

write_sstateen0,

target/riscv/csr.c +2 -0
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_SSTATEEN1] = { "sstateen1", sstateen, read_sstateen,

write_sstateen1,

target/riscv/csr.c +2 -0
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_SSTATEEN2] = { "sstateen2", sstateen, read_sstateen,

write_sstateen2,

target/riscv/csr.c +2 -0
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+    [CSR_SSTATEEN3] = { "sstateen3", sstateen, read_sstateen,

write_sstateen3,

target/riscv/csr.c +2 -0
+                        .min_priv_ver = PRIV_VERSION_1_12_0 },
+
      /* Supervisor Trap Setup */
      [CSR_SSTATUS]    = { "sstatus",    smode,

read_sstatus, write_sstatus,

                           NULL,                read_sstatus_i128  
             },
target/riscv/machine.c +20 -0
index dc182ca811..ef418ac19d 100644
@@ -262,6 +262,26 @@ static int riscv_cpu_post_load(void *opaque,
 int version_id)
      return 0;
  }
 
+static bool smstateen_needed(void *opaque)
+{
+    RISCVCPU *cpu = opaque;
+
+    return cpu->cfg.ext_smstateen;
+}
+
+static const VMStateDescription vmstate_smstateen = {
+    .name = "cpu/smtateen",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = smstateen_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64_ARRAY(env.mstateen, RISCVCPU, 4),
+        VMSTATE_UINT64_ARRAY(env.hstateen, RISCVCPU, 4),
+        VMSTATE_UINT64_ARRAY(env.sstateen, RISCVCPU, 4),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
  static bool envcfg_needed(void *opaque)
  {
      RISCVCPU *cpu = opaque;
target/riscv/machine.c +1 -0
@@ -372,6 +392,7 @@ const VMStateDescription vmstate_riscv_cpu = {
          &vmstate_kvmtimer,
          &vmstate_envcfg,
          &vmstate_debug,
+        &vmstate_smstateen,
          NULL
      }
  };
#4 lore raw

PATCH v7 2/4 target/riscv: smstateen check for h/senvcfg

In reply to Mayuresh Chitale

Accesses to henvcfg, henvcfgh and senvcfg are allowed only if corresponding bit in mstateen0/hstateen0 is enabled. Otherwise an illegal instruction trap is generated.

---
 roms/opensbi       |  2 +-
 target/riscv/csr.c | 83 ++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 77 insertions(+), 8 deletions(-)
roms/opensbi +1 -1
index 4489876e93..48f91ee9c9 160000
@@ -1 +1 @@
-Subproject commit 4489876e933d8ba0d8bc6c64bae71e295d45faac
+Subproject commit 48f91ee9c960f048c4a7d1da4447d31e04931e38
target/riscv/csr.c +76 -7

159 lines not on this page · raw message

Signature · 1 line
2.25.1
#5 lore raw

Re: [PATCH v7 2/4] target/riscv: smstateen check for h/senvcfg

Quoted 41 lines · Mayuresh Chitale

Accesses to henvcfg, henvcfgh and senvcfg are allowed only if corresponding bit in mstateen0/hstateen0 is enabled. Otherwise an illegal instruction trap is generated.

---
  roms/opensbi       |  2 +-
  target/riscv/csr.c | 83 ++++++++++++++++++++++++++++++++++++++++++----
  2 files changed, 77 insertions(+), 8 deletions(-)
roms/opensbi +1 -1
index 4489876e93..48f91ee9c9 160000
@@ -1 +1 @@
-Subproject commit 4489876e933d8ba0d8bc6c64bae71e295d45faac
+Subproject commit 48f91ee9c960f048c4a7d1da4447d31e04931e38
target/riscv/csr.c +16 -0
index ad1642fb9b..011d6c5976 100644
@@ -40,6 +40,38 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops)
  }
 
  /* Predicates */
+#if !defined(CONFIG_USER_ONLY)
+static RISCVException smstateen_acc_ok(CPURISCVState *env, int index,
+                                       uint64_t bit)
+{
+    bool virt = riscv_cpu_virt_enabled(env);
+    CPUState *cs = env_cpu(env);
+    RISCVCPU *cpu = RISCV_CPU(cs);
+
+    if (env->priv == PRV_M || !cpu->cfg.ext_smstateen) {
+        return RISCV_EXCP_NONE;
+    }
+
+    if (!(env->mstateen[index] & bit)) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+

target/riscv/csr.c void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops) · line 68

Quoted 10 lines
target/riscv/csr.c +10 -0
+    if (virt) {
+        if (!(env->hstateen[index] & bit)) {
+            return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+        }
+    }
+
+    if (env->priv == PRV_U && riscv_has_ext(env, RVS)) {
+        if (!(env->sstateen[index] & bit)) {
+            return RISCV_EXCP_ILLEGAL_INST;
+        }

VU mode seems not be taken into consideration. For VU mode, the exception will be

RISCV_EXCP_VIRT_INSTRUCTION_FAULT instead if "!(env->sstateen[index] & bit)" here.

Regards,

Weiwei Li

Quoted 140 lines
target/riscv/csr.c +50 -7
+    }
+
+    return RISCV_EXCP_NONE;
+}
+#endif
+
  static RISCVException fs(CPURISCVState *env, int csrno)
  {
  #if !defined(CONFIG_USER_ONLY)
@@ -1715,6 +1747,13 @@ static RISCVException write_menvcfgh(CPURISCVState *env, int csrno,
  static RISCVException read_senvcfg(CPURISCVState *env, int csrno,
                                   target_ulong *val)
  {
+    RISCVException ret;
+
+    ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
      *val = env->senvcfg;
      return RISCV_EXCP_NONE;
  }
@@ -1723,15 +1762,27 @@ static RISCVException write_senvcfg(CPURISCVState *env, int csrno,
                                    target_ulong val)
  {
      uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE | SENVCFG_CBZE;
+    RISCVException ret;
 
-    env->senvcfg = (env->senvcfg & ~mask) | (val & mask);
+    ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
 
+    env->senvcfg = (env->senvcfg & ~mask) | (val & mask);
      return RISCV_EXCP_NONE;
  }
 
  static RISCVException read_henvcfg(CPURISCVState *env, int csrno,
                                   target_ulong *val)
  {
+    RISCVException ret;
+
+    ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
      *val = env->henvcfg;
      return RISCV_EXCP_NONE;
  }
@@ -1740,6 +1791,12 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
                                    target_ulong val)
  {
      uint64_t mask = HENVCFG_FIOM | HENVCFG_CBIE | HENVCFG_CBCFE | HENVCFG_CBZE;
+    RISCVException ret;
+
+    ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
 
      if (riscv_cpu_mxl(env) == MXL_RV64) {
          mask |= HENVCFG_PBMTE | HENVCFG_STCE;
@@ -1753,6 +1810,13 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
  static RISCVException read_henvcfgh(CPURISCVState *env, int csrno,
                                   target_ulong *val)
  {
+    RISCVException ret;
+
+    ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
      *val = env->henvcfg >> 32;
      return RISCV_EXCP_NONE;
  }
@@ -1762,9 +1826,14 @@ static RISCVException write_henvcfgh(CPURISCVState *env, int csrno,
  {
      uint64_t mask = HENVCFG_PBMTE | HENVCFG_STCE;
      uint64_t valh = (uint64_t)val << 32;
+    RISCVException ret;
 
-    env->henvcfg = (env->henvcfg & ~mask) | (valh & mask);
+    ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
 
+    env->henvcfg = (env->henvcfg & ~mask) | (valh & mask);
      return RISCV_EXCP_NONE;
  }
 
@@ -1796,7 +1865,7 @@ static RISCVException write_mstateen(CPURISCVState *env, int csrno,
  static RISCVException write_mstateen0(CPURISCVState *env, int csrno,
                                        target_ulong new_val)
  {
-    uint64_t wr_mask = SMSTATEEN_STATEEN;
+    uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
      return write_mstateen(env, csrno, wr_mask, new_val);
  }
@@ -1843,7 +1912,7 @@ static RISCVException write_mstateenh(CPURISCVState *env, int csrno,
  static RISCVException write_mstateen0h(CPURISCVState *env, int csrno,
                                        target_ulong new_val)
  {
-    uint64_t wr_mask = SMSTATEEN_STATEEN;
+    uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
      return write_mstateenh(env, csrno, wr_mask, new_val);
  }
@@ -1892,7 +1961,7 @@ static RISCVException write_hstateen(CPURISCVState *env, int csrno,
  static RISCVException write_hstateen0(CPURISCVState *env, int csrno,
                                        target_ulong new_val)
  {
-    uint64_t wr_mask = SMSTATEEN_STATEEN;
+    uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
      return write_hstateen(env, csrno, wr_mask, new_val);
  }
@@ -1943,7 +2012,7 @@ static RISCVException write_hstateenh(CPURISCVState *env, int csrno,
  static RISCVException write_hstateen0h(CPURISCVState *env, int csrno,
                                         target_ulong new_val)
  {
-    uint64_t wr_mask = SMSTATEEN_STATEEN;
+    uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
      return write_hstateenh(env, csrno, wr_mask, new_val);
  }
@@ -2002,7 +2071,7 @@ static RISCVException write_sstateen(CPURISCVState *env, int csrno,
  static RISCVException write_sstateen0(CPURISCVState *env, int csrno,
                                        target_ulong new_val)
  {
-    uint64_t wr_mask = SMSTATEEN_STATEEN;
+    uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
      return write_sstateen(env, csrno, wr_mask, new_val);
  }
#6 lore raw

Re: [PATCH v7 2/4] target/riscv: smstateen check for h/senvcfg

Quoted 59 lines · Weiwei Li
Quoted 44 lines · Mayuresh Chitale

Accesses to henvcfg, henvcfgh and senvcfg are allowed only if corresponding bit in mstateen0/hstateen0 is enabled. Otherwise an illegal instruction trap is generated.

---
  roms/opensbi       |  2 +-
  target/riscv/csr.c | 83
++++++++++++++++++++++++++++++++++++++++++----
  2 files changed, 77 insertions(+), 8 deletions(-)
roms/opensbi +1 -1
index 4489876e93..48f91ee9c9 160000
@@ -1 +1 @@
-Subproject commit 4489876e933d8ba0d8bc6c64bae71e295d45faac
+Subproject commit 48f91ee9c960f048c4a7d1da4447d31e04931e38
target/riscv/csr.c +16 -0
index ad1642fb9b..011d6c5976 100644
@@ -40,6 +40,38 @@ void riscv_set_csr_ops(int csrno,
 riscv_csr_operations *ops)
  }
 
  /* Predicates */
+#if !defined(CONFIG_USER_ONLY)
+static RISCVException smstateen_acc_ok(CPURISCVState *env, int
 index,
+                                       uint64_t bit)
+{
+    bool virt = riscv_cpu_virt_enabled(env);
+    CPUState *cs = env_cpu(env);
+    RISCVCPU *cpu = RISCV_CPU(cs);
+
+    if (env->priv == PRV_M || !cpu->cfg.ext_smstateen) {
+        return RISCV_EXCP_NONE;
+    }
+
+    if (!(env->mstateen[index] & bit)) {
+        return RISCV_EXCP_ILLEGAL_INST;
+    }
+

target/riscv/csr.c void riscv_set_csr_ops(int csrno, · line 70

Quoted 10 lines
target/riscv/csr.c +10 -0
+    if (virt) {
+        if (!(env->hstateen[index] & bit)) {
+            return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+        }
+    }
+
+    if (env->priv == PRV_U && riscv_has_ext(env, RVS)) {
+        if (!(env->sstateen[index] & bit)) {
+            return RISCV_EXCP_ILLEGAL_INST;
+        }

VU mode seems not be taken into consideration. For VU mode, the exception will be

Quoted 2 lines

RISCV_EXCP_VIRT_INSTRUCTION_FAULT instead if "!(env->sstateen[index] & bit)" here.

Ok. I will fix it in the next version.

Quoted 164 lines

Regards,

Weiwei Li

Quoted 158 lines
target/riscv/csr.c +6 -0
+    }
+
+    return RISCV_EXCP_NONE;
+}
+#endif
+
  static RISCVException fs(CPURISCVState *env, int csrno)
  {
  #if !defined(CONFIG_USER_ONLY)
target/riscv/csr.c +7 -0
@@ -1715,6 +1747,13 @@ static RISCVException
 write_menvcfgh(CPURISCVState *env, int csrno,
  static RISCVException read_senvcfg(CPURISCVState *env, int csrno,
                                   target_ulong *val)
  {
+    RISCVException ret;
+
+    ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
      *val = env->senvcfg;
      return RISCV_EXCP_NONE;
  }
target/riscv/csr.c +13 -1
@@ -1723,15 +1762,27 @@ static RISCVException
 write_senvcfg(CPURISCVState *env, int csrno,
                                    target_ulong val)
  {
      uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE |
 SENVCFG_CBZE;
+    RISCVException ret;
 
-    env->senvcfg = (env->senvcfg & ~mask) | (val & mask);
+    ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
 
+    env->senvcfg = (env->senvcfg & ~mask) | (val & mask);
      return RISCV_EXCP_NONE;
  }
 
  static RISCVException read_henvcfg(CPURISCVState *env, int csrno,
                                   target_ulong *val)
  {
+    RISCVException ret;
+
+    ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
      *val = env->henvcfg;
      return RISCV_EXCP_NONE;

}

target/riscv/csr.c +6 -0
@@ -1740,6 +1791,12 @@ static RISCVException
 write_henvcfg(CPURISCVState *env, int csrno,
                                    target_ulong val)
  {
      uint64_t mask = HENVCFG_FIOM | HENVCFG_CBIE | HENVCFG_CBCFE |
 HENVCFG_CBZE;
+    RISCVException ret;
+
+    ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
 
      if (riscv_cpu_mxl(env) == MXL_RV64) {
          mask |= HENVCFG_PBMTE | HENVCFG_STCE;
target/riscv/csr.c +7 -0
@@ -1753,6 +1810,13 @@ static RISCVException
 write_henvcfg(CPURISCVState *env, int csrno,
  static RISCVException read_henvcfgh(CPURISCVState *env, int
 csrno,
                                   target_ulong *val)
  {
+    RISCVException ret;
+
+    ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
      *val = env->henvcfg >> 32;
      return RISCV_EXCP_NONE;

}

target/riscv/csr.c +7 -2
@@ -1762,9 +1826,14 @@ static RISCVException
 write_henvcfgh(CPURISCVState *env, int csrno,
  {
      uint64_t mask = HENVCFG_PBMTE | HENVCFG_STCE;
      uint64_t valh = (uint64_t)val << 32;
+    RISCVException ret;
 
-    env->henvcfg = (env->henvcfg & ~mask) | (valh & mask);
+    ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
 
+    env->henvcfg = (env->henvcfg & ~mask) | (valh & mask);
      return RISCV_EXCP_NONE;
  }
@@ -1796,7 +1865,7 @@ static RISCVException
 write_mstateen(CPURISCVState *env, int csrno,
  static RISCVException write_mstateen0(CPURISCVState *env, int
 csrno,
                                        target_ulong new_val)
  {
-    uint64_t wr_mask = SMSTATEEN_STATEEN;
+    uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
      return write_mstateen(env, csrno, wr_mask, new_val);

}

target/riscv/csr.c +1 -1
@@ -1843,7 +1912,7 @@ static RISCVException
 write_mstateenh(CPURISCVState *env, int csrno,
  static RISCVException write_mstateen0h(CPURISCVState *env, int
 csrno,
                                        target_ulong new_val)
  {
-    uint64_t wr_mask = SMSTATEEN_STATEEN;
+    uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
      return write_mstateenh(env, csrno, wr_mask, new_val);

}

target/riscv/csr.c +1 -1
@@ -1892,7 +1961,7 @@ static RISCVException
 write_hstateen(CPURISCVState *env, int csrno,
  static RISCVException write_hstateen0(CPURISCVState *env, int
 csrno,
                                        target_ulong new_val)
  {
-    uint64_t wr_mask = SMSTATEEN_STATEEN;
+    uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
      return write_hstateen(env, csrno, wr_mask, new_val);

}

target/riscv/csr.c +1 -1
@@ -1943,7 +2012,7 @@ static RISCVException
 write_hstateenh(CPURISCVState *env, int csrno,
  static RISCVException write_hstateen0h(CPURISCVState *env, int
 csrno,
                                         target_ulong new_val)
  {
-    uint64_t wr_mask = SMSTATEEN_STATEEN;
+    uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
      return write_hstateenh(env, csrno, wr_mask, new_val);

}

target/riscv/csr.c +1 -1
@@ -2002,7 +2071,7 @@ static RISCVException
 write_sstateen(CPURISCVState *env, int csrno,
  static RISCVException write_sstateen0(CPURISCVState *env, int
 csrno,
                                        target_ulong new_val)
  {
-    uint64_t wr_mask = SMSTATEEN_STATEEN;
+    uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
      return write_sstateen(env, csrno, wr_mask, new_val);

}

#7 lore raw

PATCH v7 3/4 target/riscv: smstateen check for fcsr

In reply to Mayuresh Chitale

If smstateen is implemented and sstateen0.fcsr is clear then the floating point operations must return illegal instruction exception.

---
 target/riscv/csr.c                        | 23 +++++++++++++
 target/riscv/insn_trans/trans_rvf.c.inc   | 40 +++++++++++++++++++++--
 target/riscv/insn_trans/trans_rvzfh.c.inc | 12 +++++++
 3 files changed, 72 insertions(+), 3 deletions(-)
target/riscv/csr.c +23 -0
index 011d6c5976..0512391220 100644
@@ -79,6 +79,10 @@ static RISCVException fs(CPURISCVState *env, int csrno)
         !RISCV_CPU(env_cpu(env))->cfg.ext_zfinx) {
         return RISCV_EXCP_ILLEGAL_INST;
     }
+
+    if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
+        return smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR);
+    }
 #endif
     return RISCV_EXCP_NONE;
 }
@@ -1866,6 +1870,9 @@ static RISCVException write_mstateen0(CPURISCVState *env, int csrno,
                                       target_ulong new_val)
 {
     uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
 
     return write_mstateen(env, csrno, wr_mask, new_val);
 }
@@ -1914,6 +1921,10 @@ static RISCVException write_mstateen0h(CPURISCVState *env, int csrno,
 {
     uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
+
     return write_mstateenh(env, csrno, wr_mask, new_val);
 }
 
@@ -1963,6 +1974,10 @@ static RISCVException write_hstateen0(CPURISCVState *env, int csrno,
 {
     uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
+
     return write_hstateen(env, csrno, wr_mask, new_val);
 }
 
@@ -2014,6 +2029,10 @@ static RISCVException write_hstateen0h(CPURISCVState *env, int csrno,
 {
     uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
+
     return write_hstateenh(env, csrno, wr_mask, new_val);
 }
 
@@ -2073,6 +2092,10 @@ static RISCVException write_sstateen0(CPURISCVState *env, int csrno,
 {
     uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
+
     return write_sstateen(env, csrno, wr_mask, new_val);
 }
 
target/riscv/insn_trans/trans_rvf.c.inc +37 -3
index a1d3eb52ad..ce8a0cc34b 100644
@@ -24,9 +24,43 @@
             return false; \
 } while (0)
 
-#define REQUIRE_ZFINX_OR_F(ctx) do {\
-    if (!ctx->cfg_ptr->ext_zfinx) { \
-        REQUIRE_EXT(ctx, RVF); \
+#ifndef CONFIG_USER_ONLY
+static inline bool smstateen_check(DisasContext *ctx, int index)
+{
+    CPUState *cpu = ctx->cs;
+    CPURISCVState *env = cpu->env_ptr;
+    uint64_t stateen = env->mstateen[index];
+
+    if (!ctx->cfg_ptr->ext_smstateen || env->priv == PRV_M) {
+        return true;
+    }
+
+    if (ctx->virt_enabled) {
+        stateen &= env->hstateen[index];
+    }
+
+    if (env->priv == PRV_U && has_ext(ctx, RVS)) {
+        stateen &= env->sstateen[index];
+    }
+
+    if (!(stateen & SMSTATEEN0_FCSR)) {
+        return false;
+    }
+
+    return true;
+}
+#else
+#define smstateen_check(ctx, index) (true)
+#endif
+
+#define REQUIRE_ZFINX_OR_F(ctx) do { \
+    if (!has_ext(ctx, RVF)) { \
+        if (!ctx->cfg_ptr->ext_zfinx) { \
+            return false; \
+        } \
+        if (!smstateen_check(ctx, 0)) { \
+            return false; \
+        } \
     } \
 } while (0)
 
target/riscv/insn_trans/trans_rvzfh.c.inc +12 -0
index 5d07150cd0..44d962c920 100644
@@ -20,18 +20,27 @@
     if (!ctx->cfg_ptr->ext_zfh) {      \
         return false;         \
     }                         \
+    if (!smstateen_check(ctx, 0)) { \
+        return false; \
+    } \
 } while (0)
 
 #define REQUIRE_ZHINX_OR_ZFH(ctx) do { \
     if (!ctx->cfg_ptr->ext_zhinx && !ctx->cfg_ptr->ext_zfh) { \
         return false;                  \
     }                                  \
+    if (!smstateen_check(ctx, 0)) { \
+        return false; \
+    } \
 } while (0)
 
 #define REQUIRE_ZFH_OR_ZFHMIN(ctx) do {       \
     if (!(ctx->cfg_ptr->ext_zfh || ctx->cfg_ptr->ext_zfhmin)) { \
         return false;                         \
     }                                         \
+    if (!smstateen_check(ctx, 0)) { \
+        return false; \
+    } \
 } while (0)
 
 #define REQUIRE_ZFH_OR_ZFHMIN_OR_ZHINX_OR_ZHINXMIN(ctx) do { \
@@ -39,6 +48,9 @@
           ctx->cfg_ptr->ext_zhinx || ctx->cfg_ptr->ext_zhinxmin)) {     \
         return false;                                        \
     }                                                        \
+    if (!smstateen_check(ctx, 0)) { \
+        return false; \
+    } \
 } while (0)
 
 static bool trans_flh(DisasContext *ctx, arg_flh *a)
Signature · 1 line
2.25.1
#8 lore raw

Re: [PATCH v7 3/4] target/riscv: smstateen check for fcsr

Quoted 2 lines · Mayuresh Chitale

If smstateen is implemented and sstateen0.fcsr is clear then the floating point operations must return illegal instruction exception.

I think this is not correct. The exception for float point operations must be illegal instruction exception

if FCSR is not existed(that is misa.F is zero and Zfinx is not supported). However, when FCSR is exsited,

the final exception should be decided by current privilege level and the stateen related csr values just

like the access control of FCSR.

Regards,

Weiwei Li

Quoted 170 lines
---
  target/riscv/csr.c                        | 23 +++++++++++++
  target/riscv/insn_trans/trans_rvf.c.inc   | 40 +++++++++++++++++++++--
  target/riscv/insn_trans/trans_rvzfh.c.inc | 12 +++++++
  3 files changed, 72 insertions(+), 3 deletions(-)
target/riscv/csr.c +23 -0
index 011d6c5976..0512391220 100644
@@ -79,6 +79,10 @@ static RISCVException fs(CPURISCVState *env, int csrno)
          !RISCV_CPU(env_cpu(env))->cfg.ext_zfinx) {
          return RISCV_EXCP_ILLEGAL_INST;
      }
+
+    if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
+        return smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR);
+    }
  #endif
      return RISCV_EXCP_NONE;
  }
@@ -1866,6 +1870,9 @@ static RISCVException write_mstateen0(CPURISCVState *env, int csrno,
                                        target_ulong new_val)
  {
      uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
 
      return write_mstateen(env, csrno, wr_mask, new_val);
  }
@@ -1914,6 +1921,10 @@ static RISCVException write_mstateen0h(CPURISCVState *env, int csrno,
  {
      uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
+
      return write_mstateenh(env, csrno, wr_mask, new_val);
  }
 
@@ -1963,6 +1974,10 @@ static RISCVException write_hstateen0(CPURISCVState *env, int csrno,
  {
      uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
+
      return write_hstateen(env, csrno, wr_mask, new_val);
  }
 
@@ -2014,6 +2029,10 @@ static RISCVException write_hstateen0h(CPURISCVState *env, int csrno,
  {
      uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
+
      return write_hstateenh(env, csrno, wr_mask, new_val);
  }
 
@@ -2073,6 +2092,10 @@ static RISCVException write_sstateen0(CPURISCVState *env, int csrno,
  {
      uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
+
      return write_sstateen(env, csrno, wr_mask, new_val);
  }
 
target/riscv/insn_trans/trans_rvf.c.inc +37 -3
index a1d3eb52ad..ce8a0cc34b 100644
@@ -24,9 +24,43 @@
              return false; \
  } while (0)
 
-#define REQUIRE_ZFINX_OR_F(ctx) do {\
-    if (!ctx->cfg_ptr->ext_zfinx) { \
-        REQUIRE_EXT(ctx, RVF); \
+#ifndef CONFIG_USER_ONLY
+static inline bool smstateen_check(DisasContext *ctx, int index)
+{
+    CPUState *cpu = ctx->cs;
+    CPURISCVState *env = cpu->env_ptr;
+    uint64_t stateen = env->mstateen[index];
+
+    if (!ctx->cfg_ptr->ext_smstateen || env->priv == PRV_M) {
+        return true;
+    }
+
+    if (ctx->virt_enabled) {
+        stateen &= env->hstateen[index];
+    }
+
+    if (env->priv == PRV_U && has_ext(ctx, RVS)) {
+        stateen &= env->sstateen[index];
+    }
+
+    if (!(stateen & SMSTATEEN0_FCSR)) {
+        return false;
+    }
+
+    return true;
+}
+#else
+#define smstateen_check(ctx, index) (true)
+#endif
+
+#define REQUIRE_ZFINX_OR_F(ctx) do { \
+    if (!has_ext(ctx, RVF)) { \
+        if (!ctx->cfg_ptr->ext_zfinx) { \
+            return false; \
+        } \
+        if (!smstateen_check(ctx, 0)) { \
+            return false; \
+        } \
      } \
  } while (0)
 
target/riscv/insn_trans/trans_rvzfh.c.inc +12 -0
index 5d07150cd0..44d962c920 100644
@@ -20,18 +20,27 @@
      if (!ctx->cfg_ptr->ext_zfh) {      \
          return false;         \
      }                         \
+    if (!smstateen_check(ctx, 0)) { \
+        return false; \
+    } \
  } while (0)
 
  #define REQUIRE_ZHINX_OR_ZFH(ctx) do { \
      if (!ctx->cfg_ptr->ext_zhinx && !ctx->cfg_ptr->ext_zfh) { \
          return false;                  \
      }                                  \
+    if (!smstateen_check(ctx, 0)) { \
+        return false; \
+    } \
  } while (0)
 
  #define REQUIRE_ZFH_OR_ZFHMIN(ctx) do {       \
      if (!(ctx->cfg_ptr->ext_zfh || ctx->cfg_ptr->ext_zfhmin)) { \
          return false;                         \
      }                                         \
+    if (!smstateen_check(ctx, 0)) { \
+        return false; \
+    } \
  } while (0)
 
  #define REQUIRE_ZFH_OR_ZFHMIN_OR_ZHINX_OR_ZHINXMIN(ctx) do { \
@@ -39,6 +48,9 @@
            ctx->cfg_ptr->ext_zhinx || ctx->cfg_ptr->ext_zhinxmin)) {     \
          return false;                                        \
      }                                                        \
+    if (!smstateen_check(ctx, 0)) { \
+        return false; \
+    } \
  } while (0)
 
  static bool trans_flh(DisasContext *ctx, arg_flh *a)
#9 lore raw

Re: [PATCH v7 3/4] target/riscv: smstateen check for fcsr

Quoted 9 lines · Weiwei Li
Quoted 3 lines · Mayuresh Chitale

If smstateen is implemented and sstateen0.fcsr is clear then the floating point operations must return illegal instruction exception.

I think this is not correct. The exception for float point operations
must be illegal instruction exception

Quoted 8 lines

if FCSR is not existed(that is misa.F is zero and Zfinx is not supported). However, when FCSR is exsited,

the final exception should be decided by current privilege level and the
stateen related csr values just

like the access control of FCSR.

Ok. We can use the language from the spec itself.

Quoted 184 lines

Regards,

Weiwei Li

Quoted 179 lines
---
  target/riscv/csr.c                        | 23 +++++++++++++
  target/riscv/insn_trans/trans_rvf.c.inc   | 40
+++++++++++++++++++++--
  target/riscv/insn_trans/trans_rvzfh.c.inc | 12 +++++++
  3 files changed, 72 insertions(+), 3 deletions(-)
target/riscv/csr.c +4 -0
index 011d6c5976..0512391220 100644
@@ -79,6 +79,10 @@ static RISCVException fs(CPURISCVState *env, int
 csrno)
          !RISCV_CPU(env_cpu(env))->cfg.ext_zfinx) {
          return RISCV_EXCP_ILLEGAL_INST;
      }
+
+    if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
+        return smstateen_acc_ok(env, 0, SMSTATEEN0_FCSR);
+    }
  #endif
      return RISCV_EXCP_NONE;
  }
target/riscv/csr.c +3 -0
@@ -1866,6 +1870,9 @@ static RISCVException
 write_mstateen0(CPURISCVState *env, int csrno,
                                        target_ulong new_val)
  {
      uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
 
      return write_mstateen(env, csrno, wr_mask, new_val);
  }
target/riscv/csr.c +16 -0
@@ -1914,6 +1921,10 @@ static RISCVException
 write_mstateen0h(CPURISCVState *env, int csrno,
  {
      uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
+
      return write_mstateenh(env, csrno, wr_mask, new_val);
  }
@@ -1963,6 +1974,10 @@ static RISCVException
 write_hstateen0(CPURISCVState *env, int csrno,
  {
      uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
+
      return write_hstateen(env, csrno, wr_mask, new_val);
  }
@@ -2014,6 +2029,10 @@ static RISCVException
 write_hstateen0h(CPURISCVState *env, int csrno,
  {
      uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
+
      return write_hstateenh(env, csrno, wr_mask, new_val);
  }
@@ -2073,6 +2092,10 @@ static RISCVException
 write_sstateen0(CPURISCVState *env, int csrno,
  {
      uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
 
+    if (!riscv_has_ext(env, RVF)) {
+        wr_mask |= SMSTATEEN0_FCSR;
+    }
+
      return write_sstateen(env, csrno, wr_mask, new_val);
  }
target/riscv/insn_trans/trans_rvf.c.inc +37 -3
index a1d3eb52ad..ce8a0cc34b 100644
@@ -24,9 +24,43 @@
              return false; \
  } while (0)
 
-#define REQUIRE_ZFINX_OR_F(ctx) do {\
-    if (!ctx->cfg_ptr->ext_zfinx) { \
-        REQUIRE_EXT(ctx, RVF); \
+#ifndef CONFIG_USER_ONLY
+static inline bool smstateen_check(DisasContext *ctx, int index)
+{
+    CPUState *cpu = ctx->cs;
+    CPURISCVState *env = cpu->env_ptr;
+    uint64_t stateen = env->mstateen[index];
+
+    if (!ctx->cfg_ptr->ext_smstateen || env->priv == PRV_M) {
+        return true;
+    }
+
+    if (ctx->virt_enabled) {
+        stateen &= env->hstateen[index];
+    }
+
+    if (env->priv == PRV_U && has_ext(ctx, RVS)) {
+        stateen &= env->sstateen[index];
+    }
+
+    if (!(stateen & SMSTATEEN0_FCSR)) {
+        return false;
+    }
+
+    return true;
+}
+#else
+#define smstateen_check(ctx, index) (true)
+#endif
+
+#define REQUIRE_ZFINX_OR_F(ctx) do { \
+    if (!has_ext(ctx, RVF)) { \
+        if (!ctx->cfg_ptr->ext_zfinx) { \
+            return false; \
+        } \
+        if (!smstateen_check(ctx, 0)) { \
+            return false; \
+        } \
      } \
  } while (0)
 
target/riscv/insn_trans/trans_rvzfh.c.inc +12 -0
index 5d07150cd0..44d962c920 100644
@@ -20,18 +20,27 @@
      if (!ctx->cfg_ptr->ext_zfh) {      \
          return false;         \
      }                         \
+    if (!smstateen_check(ctx, 0)) { \
+        return false; \
+    } \
  } while (0)
 
  #define REQUIRE_ZHINX_OR_ZFH(ctx) do { \
      if (!ctx->cfg_ptr->ext_zhinx && !ctx->cfg_ptr->ext_zfh) { \
          return false;                  \
      }                                  \
+    if (!smstateen_check(ctx, 0)) { \
+        return false; \
+    } \
  } while (0)
 
  #define REQUIRE_ZFH_OR_ZFHMIN(ctx) do {       \
      if (!(ctx->cfg_ptr->ext_zfh || ctx->cfg_ptr->ext_zfhmin)) { \
          return false;                         \
      }                                         \
+    if (!smstateen_check(ctx, 0)) { \
+        return false; \
+    } \
  } while (0)
 
  #define REQUIRE_ZFH_OR_ZFHMIN_OR_ZHINX_OR_ZHINXMIN(ctx) do { \
@@ -39,6 +48,9 @@
            ctx->cfg_ptr->ext_zhinx || ctx->cfg_ptr->ext_zhinxmin)) 
 {     \
          return false;                                        \
      }                                                        \
+    if (!smstateen_check(ctx, 0)) { \
+        return false; \
+    } \
  } while (0)
 

static bool trans_flh(DisasContext *ctx, arg_flh *a)

#10 lore raw

PATCH v7 4/4 target/riscv: smstateen knobs

In reply to Mayuresh Chitale

Add knobs to allow users to enable smstateen and also export it via the ISA extension string.

---
 target/riscv/cpu.c | 2 ++
 1 file changed, 2 insertions(+)
target/riscv/cpu.c +2 -0
index d4635c7df4..d8a0f4e700 100644
@@ -99,6 +99,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
     ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f),
     ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx),
     ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin),
+    ISA_EXT_DATA_ENTRY(smstateen, true, PRIV_VERSION_1_12_0, ext_smstateen),
     ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
     ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot),
     ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt),
@@ -1001,6 +1002,7 @@ static Property riscv_cpu_extensions[] = {
     DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
     DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
 
+    DEFINE_PROP_BOOL("smstateen", RISCVCPU, cfg.ext_smstateen, false),
     DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
     DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
     DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
Signature · 1 line
2.25.1