Skip to content

Commit 38c83e8

Browse files
rockindyalistair23
authored andcommitted
target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR
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> Signed-off-by: Alvin Chang <alvinga@andestech.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <172100444279.18077.6893072378718059541-0@git.sr.ht> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
1 parent 6f6592d commit 38c83e8

File tree

3 files changed

+58
-9
lines changed

3 files changed

+58
-9
lines changed

target/riscv/cpu.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
751751
void riscv_cpu_update_mask(CPURISCVState *env);
752752
bool riscv_cpu_is_32bit(RISCVCPU *cpu);
753753

754+
RISCVException riscv_csrr(CPURISCVState *env, int csrno,
755+
target_ulong *ret_value);
754756
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
755757
target_ulong *ret_value,
756758
target_ulong new_value, target_ulong write_mask);
@@ -783,6 +785,8 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
783785
target_ulong new_value,
784786
target_ulong write_mask);
785787

788+
RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
789+
Int128 *ret_value);
786790
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
787791
Int128 *ret_value,
788792
Int128 new_value, Int128 write_mask);

target/riscv/csr.c

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4624,7 +4624,7 @@ static RISCVException rmw_seed(CPURISCVState *env, int csrno,
46244624

46254625
static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
46264626
int csrno,
4627-
bool write_mask)
4627+
bool write)
46284628
{
46294629
/* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
46304630
bool read_only = get_field(csrno, 0xC00) == 3;
@@ -4646,7 +4646,7 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
46464646
}
46474647

46484648
/* read / write check */
4649-
if (write_mask && read_only) {
4649+
if (write && read_only) {
46504650
return RISCV_EXCP_ILLEGAL_INST;
46514651
}
46524652

@@ -4733,11 +4733,22 @@ static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno,
47334733
return RISCV_EXCP_NONE;
47344734
}
47354735

4736+
RISCVException riscv_csrr(CPURISCVState *env, int csrno,
4737+
target_ulong *ret_value)
4738+
{
4739+
RISCVException ret = riscv_csrrw_check(env, csrno, false);
4740+
if (ret != RISCV_EXCP_NONE) {
4741+
return ret;
4742+
}
4743+
4744+
return riscv_csrrw_do64(env, csrno, ret_value, 0, 0);
4745+
}
4746+
47364747
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
47374748
target_ulong *ret_value,
47384749
target_ulong new_value, target_ulong write_mask)
47394750
{
4740-
RISCVException ret = riscv_csrrw_check(env, csrno, write_mask);
4751+
RISCVException ret = riscv_csrrw_check(env, csrno, true);
47414752
if (ret != RISCV_EXCP_NONE) {
47424753
return ret;
47434754
}
@@ -4785,13 +4796,45 @@ static RISCVException riscv_csrrw_do128(CPURISCVState *env, int csrno,
47854796
return RISCV_EXCP_NONE;
47864797
}
47874798

4799+
RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
4800+
Int128 *ret_value)
4801+
{
4802+
RISCVException ret;
4803+
4804+
ret = riscv_csrrw_check(env, csrno, false);
4805+
if (ret != RISCV_EXCP_NONE) {
4806+
return ret;
4807+
}
4808+
4809+
if (csr_ops[csrno].read128) {
4810+
return riscv_csrrw_do128(env, csrno, ret_value,
4811+
int128_zero(), int128_zero());
4812+
}
4813+
4814+
/*
4815+
* Fall back to 64-bit version for now, if the 128-bit alternative isn't
4816+
* at all defined.
4817+
* Note, some CSRs don't need to extend to MXLEN (64 upper bits non
4818+
* significant), for those, this fallback is correctly handling the
4819+
* accesses
4820+
*/
4821+
target_ulong old_value;
4822+
ret = riscv_csrrw_do64(env, csrno, &old_value,
4823+
(target_ulong)0,
4824+
(target_ulong)0);
4825+
if (ret == RISCV_EXCP_NONE && ret_value) {
4826+
*ret_value = int128_make64(old_value);
4827+
}
4828+
return ret;
4829+
}
4830+
47884831
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
47894832
Int128 *ret_value,
47904833
Int128 new_value, Int128 write_mask)
47914834
{
47924835
RISCVException ret;
47934836

4794-
ret = riscv_csrrw_check(env, csrno, int128_nz(write_mask));
4837+
ret = riscv_csrrw_check(env, csrno, true);
47954838
if (ret != RISCV_EXCP_NONE) {
47964839
return ret;
47974840
}
@@ -4830,7 +4873,11 @@ RISCVException riscv_csrrw_debug(CPURISCVState *env, int csrno,
48304873
#if !defined(CONFIG_USER_ONLY)
48314874
env->debugger = true;
48324875
#endif
4833-
ret = riscv_csrrw(env, csrno, ret_value, new_value, write_mask);
4876+
if (!write_mask) {
4877+
ret = riscv_csrr(env, csrno, ret_value);
4878+
} else {
4879+
ret = riscv_csrrw(env, csrno, ret_value, new_value, write_mask);
4880+
}
48344881
#if !defined(CONFIG_USER_ONLY)
48354882
env->debugger = false;
48364883
#endif

target/riscv/op_helper.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ target_ulong helper_csrr(CPURISCVState *env, int csr)
5151
}
5252

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

5656
if (ret != RISCV_EXCP_NONE) {
5757
riscv_raise_exception(env, ret, GETPC());
@@ -84,9 +84,7 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
8484
target_ulong helper_csrr_i128(CPURISCVState *env, int csr)
8585
{
8686
Int128 rv = int128_zero();
87-
RISCVException ret = riscv_csrrw_i128(env, csr, &rv,
88-
int128_zero(),
89-
int128_zero());
87+
RISCVException ret = riscv_csrr_i128(env, csr, &rv);
9088

9189
if (ret != RISCV_EXCP_NONE) {
9290
riscv_raise_exception(env, ret, GETPC());

0 commit comments

Comments
 (0)