qemu-riscv
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] target/riscv: raise an exception when CSRRS/CSRRC writes a r


From: Richard Henderson
Subject: Re: [PATCH] target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR
Date: Sat, 9 Mar 2024 08:05:04 -1000
User-agent: Mozilla Thunderbird

On 3/7/24 22:40, Yu-Ming Chang via wrote:
Both CSRRS and CSRRC always read the addressed CSR and cause any read side
effects regardless of rs1 and rd fields. Note that if rs1 specifies a register
holding a zero value other than x0, the instruction will still attempt to write
the unmodified value back to the CSR and will cause any attendant side effects.

So if CSRRS or CSRRC tries to write a read-only CSR with rs1 which specifies
a register holding a zero value, an illegal instruction exception should be
raised.

Signed-off-by: Yu-Ming Chang <yumin686@andestech.com>
---
  target/riscv/cpu.h       |  3 +++
  target/riscv/csr.c       | 18 +++++++++++++++---
  target/riscv/op_helper.c |  2 +-
  3 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 5d291a7092..087ef64889 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -710,6 +710,9 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
  void riscv_cpu_update_mask(CPURISCVState *env);
  bool riscv_cpu_is_32bit(RISCVCPU *cpu);
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
+                          target_ulong *ret_value,
+                          target_ulong new_value, target_ulong write_mask);
  RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
                             target_ulong *ret_value,
                             target_ulong new_value, target_ulong write_mask);
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d4e8ac13b9..3e49cf0df1 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -4306,7 +4306,7 @@ static RISCVException rmw_seed(CPURISCVState *env, int 
csrno,
static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
                                                 int csrno,
-                                               bool write_mask)
+                                               bool write)
  {
      /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
      bool read_only = get_field(csrno, 0xC00) == 3;
@@ -4328,7 +4328,7 @@ static inline RISCVException 
riscv_csrrw_check(CPURISCVState *env,
      }
/* read / write check */
-    if (write_mask && read_only) {
+    if (write && read_only) {
          return RISCV_EXCP_ILLEGAL_INST;
      }
@@ -4415,11 +4415,23 @@ static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno,
      return RISCV_EXCP_NONE;
  }
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
+                           target_ulong *ret_value,
+                           target_ulong new_value, target_ulong write_mask)

Remove new_value and write_mask arguments, as they don't make sense for read.

+{
+    RISCVException ret = riscv_csrrw_check(env, csrno, false);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
+    return riscv_csrrw_do64(env, csrno, ret_value, new_value, write_mask);

... and pass zeros ...

-    RISCVException ret = riscv_csrrw(env, csr, &val, 0, 0);
+    RISCVException ret = riscv_csrr(env, csr, &val, 0, 0);

... like you do from the only caller.


r~




reply via email to

[Prev in Thread] Current Thread [Next in Thread]