diff --git a/arch/riscv/cpu_bits.h b/arch/riscv/cpu_bits.h index d1bc16d63..e89d04414 100644 --- a/arch/riscv/cpu_bits.h +++ b/arch/riscv/cpu_bits.h @@ -308,8 +308,8 @@ #define MSTATUS_MXR 0x00080000 #define MSTATUS_VM 0x1F000000 /* until: priv-1.9.1 */ #define MSTATUS_TVM 0x00100000 /* since: priv-1.10 */ -#define MSTATUS_TW 0x20000000 /* since: priv-1.10 */ -#define MSTATUS_TSR 0x40000000 /* since: priv-1.10 */ +#define MSTATUS_TW 0x00200000 /* since: priv-1.10 */ +#define MSTATUS_TSR 0x00400000 /* since: priv-1.10 */ #define MSTATUS_VS_INITIAL 0x00000600 #define MSTATUS_FS_INITIAL 0x00002000 diff --git a/arch/riscv/op_helper.c b/arch/riscv/op_helper.c index 833170c3c..3f5f0eca3 100644 --- a/arch/riscv/op_helper.c +++ b/arch/riscv/op_helper.c @@ -396,6 +396,10 @@ inline void csr_write_helper(CPUState *env, target_ulong val_to_write, target_ul target_ulong mask = MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_MPP | MSTATUS_MXR | MSTATUS_VS; if(riscv_has_ext(env, RISCV_FEATURE_RVS)) { mask |= MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_SUM | MSTATUS_SPP; + + if(env->privilege_architecture >= RISCV_PRIV1_10) { + mask |= MSTATUS_TVM | MSTATUS_TW | MSTATUS_TSR; + } } if(env->privilege_architecture < RISCV_PRIV1_10) { diff --git a/arch/riscv/translate.c b/arch/riscv/translate.c index 7d873ee17..eff617a70 100644 --- a/arch/riscv/translate.c +++ b/arch/riscv/translate.c @@ -3546,6 +3546,20 @@ static void gen_system(DisasContext *dc, uint32_t opc, int rd, int rs1, int rs2, } break; case 0x9: /* SFENCE.VMA */ + /* SFENCE.VMA is privileged: U-mode must always trap */ + if(env->priv < PRV_S) { + generate_exception(dc, RISCV_EXCP_ILLEGAL_INST); + break; + } + + /* In S-mode, TVM=1 also traps (priv spec >= 1.10) */ + if(env->privilege_architecture >= RISCV_PRIV1_10 && + env->priv == PRV_S && + get_field(env->mstatus, MSTATUS_TVM)) { + generate_exception(dc, RISCV_EXCP_ILLEGAL_INST); + break; + } + /* TODO: handle ASID specific fences */ gen_helper_tlb_flush(cpu_env); break;