Message ID | 20240418133916.1442471-4-cleger@rivosinc.com |
---|---|
State | New |
Headers | show |
Series | target/riscv: Add support for Smdbltrp and Ssdbltrp extensions | expand |
On Thu, Apr 18, 2024 at 9:40 PM Clément Léger <cleger@rivosinc.com> wrote: > > The Smdbltrp extension allows to generate M-mode targeted double trap > exceptions [1]. Such exceptions are generated if a trap is taken while > mstatus.sdt is set to 1. The specification states that if the Smnrmi > extension is implemented, then the hart enters a critical-error state > and generate a critical-error signal. Since there is no Smrnmi support, > the implementation generates a cpu abort. > > Link: https://github.com/riscv/riscv-double-trap/releases/download/v0.56/riscv-double-trap.pdf [1] > Signed-off-by: Clément Léger <cleger@rivosinc.com> > --- > target/riscv/cpu.c | 5 +++++ > target/riscv/cpu_bits.h | 1 + > target/riscv/cpu_cfg.h | 1 + > target/riscv/cpu_helper.c | 6 ++++++ > target/riscv/csr.c | 12 ++++++++++++ > target/riscv/op_helper.c | 3 +++ > 6 files changed, 28 insertions(+) > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index d159b0c6b6..98f04ecb8c 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -176,6 +176,7 @@ const RISCVIsaExtData isa_edata_arr[] = { > ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx), > ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin), > ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia), > + ISA_EXT_DATA_ENTRY(smdbltrp, PRIV_VERSION_1_12_0, ext_smdbltrp), > ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp), > ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen), > ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia), > @@ -954,6 +955,9 @@ static void riscv_cpu_reset_hold(Object *obj) > env->mstatus_hs = set_field(env->mstatus_hs, > MSTATUS64_UXL, env->misa_mxl); > } > + if (riscv_cpu_cfg(env)->ext_smdbltrp) { > + env->mstatus = set_field(env->mstatus, MSTATUS_MDT, 1); > + } > } > env->mcause = 0; > env->miclaim = MIP_SGEIP; > @@ -1574,6 +1578,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { > /* These are experimental so mark with 'x-' */ > const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { > MULTI_EXT_CFG_BOOL("x-ssdbltrp", ext_ssdbltrp, false), > + MULTI_EXT_CFG_BOOL("x-smdbltrp", ext_smdbltrp, false), > DEFINE_PROP_END_OF_LIST(), > }; > > diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h > index 494a036f6e..660f2eed5b 100644 > --- a/target/riscv/cpu_bits.h > +++ b/target/riscv/cpu_bits.h > @@ -545,6 +545,7 @@ > #define MSTATUS_SDT 0x01000000 /* Ssdbltrp extension */ > #define MSTATUS_GVA 0x4000000000ULL > #define MSTATUS_MPV 0x8000000000ULL > +#define MSTATUS_MDT 0x200000000000ULL /* Smdbltrp extension */ The M-mode-disable-trap (MDT) bit is at bit 42. Regards, Tommy Wu > > #define MSTATUS64_UXL 0x0000000300000000ULL > #define MSTATUS64_SXL 0x0000000C00000000ULL > diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h > index a149c08167..cf6a802502 100644 > --- a/target/riscv/cpu_cfg.h > +++ b/target/riscv/cpu_cfg.h > @@ -75,6 +75,7 @@ struct RISCVCPUConfig { > bool ext_smstateen; > bool ext_sstc; > bool ext_ssdbltrp; > + bool ext_smdbltrp; > bool ext_svadu; > bool ext_svinval; > bool ext_svnapot; > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c > index 3d747e5bfc..5ce0982f2f 100644 > --- a/target/riscv/cpu_helper.c > +++ b/target/riscv/cpu_helper.c > @@ -1862,6 +1862,12 @@ void riscv_cpu_do_interrupt(CPUState *cs) > s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE)); > s = set_field(s, MSTATUS_MPP, env->priv); > s = set_field(s, MSTATUS_MIE, 0); > + if (riscv_cpu_cfg(env)->ext_smdbltrp) { > + if (env->mstatus & MSTATUS_MDT) > + cpu_abort(CPU(cpu), "M-mode double trap\n"); > + > + s = set_field(s, MSTATUS_MDT, 1); > + } > env->mstatus = s; > env->mcause = cause | ~(((target_ulong)-1) >> async); > if (smode_double_trap) { > diff --git a/target/riscv/csr.c b/target/riscv/csr.c > index 1a2e739947..200b06e320 100644 > --- a/target/riscv/csr.c > +++ b/target/riscv/csr.c > @@ -1363,6 +1363,7 @@ static target_ulong legalize_mpp(CPURISCVState *env, target_ulong old_mpp, > static RISCVException write_mstatus(CPURISCVState *env, int csrno, > target_ulong val) > { > + const RISCVCPUConfig *cfg = riscv_cpu_cfg(env); > uint64_t mstatus = env->mstatus; > uint64_t mask = 0; > RISCVMXL xl = riscv_cpu_mxl(env); > @@ -1396,6 +1397,12 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, > } > } > > + if (cfg->ext_smdbltrp) { > + mask |= MSTATUS_MDT; > + if ((val & MSTATUS_MDT) != 0) > + mask &= ~MSTATUS_MIE; > + } > + > if (xl != MXL_RV32 || env->debugger) { > if (riscv_has_ext(env, RVH)) { > mask |= MSTATUS_MPV | MSTATUS_GVA; > @@ -1434,6 +1441,11 @@ static RISCVException write_mstatush(CPURISCVState *env, int csrno, > uint64_t valh = (uint64_t)val << 32; > uint64_t mask = riscv_has_ext(env, RVH) ? MSTATUS_MPV | MSTATUS_GVA : 0; > > + if (riscv_cpu_cfg(env)->ext_smdbltrp) { > + mask |= MSTATUS_MDT; > + if ((val & MSTATUS_MDT) != 0) > + mask |= MSTATUS_MIE; > + } > env->mstatus = (env->mstatus & ~mask) | (valh & mask); > > return RISCV_EXCP_NONE; > diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c > index 468ee58a00..d289d14237 100644 > --- a/target/riscv/op_helper.c > +++ b/target/riscv/op_helper.c > @@ -354,6 +354,9 @@ target_ulong helper_mret(CPURISCVState *env) > mstatus = set_field(mstatus, MSTATUS_MPP, > riscv_has_ext(env, RVU) ? PRV_U : PRV_M); > mstatus = set_field(mstatus, MSTATUS_MPV, 0); > + if (riscv_cpu_cfg(env)->ext_smdbltrp) { > + mstatus = set_field(mstatus, MSTATUS_MDT, 0); > + } > if ((env->priv_ver >= PRIV_VERSION_1_12_0) && (prev_priv != PRV_M)) { > mstatus = set_field(mstatus, MSTATUS_MPRV, 0); > } > -- > 2.43.0 > >
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index d159b0c6b6..98f04ecb8c 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -176,6 +176,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx), ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin), ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia), + ISA_EXT_DATA_ENTRY(smdbltrp, PRIV_VERSION_1_12_0, ext_smdbltrp), ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp), ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen), ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia), @@ -954,6 +955,9 @@ static void riscv_cpu_reset_hold(Object *obj) env->mstatus_hs = set_field(env->mstatus_hs, MSTATUS64_UXL, env->misa_mxl); } + if (riscv_cpu_cfg(env)->ext_smdbltrp) { + env->mstatus = set_field(env->mstatus, MSTATUS_MDT, 1); + } } env->mcause = 0; env->miclaim = MIP_SGEIP; @@ -1574,6 +1578,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { /* These are experimental so mark with 'x-' */ const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { MULTI_EXT_CFG_BOOL("x-ssdbltrp", ext_ssdbltrp, false), + MULTI_EXT_CFG_BOOL("x-smdbltrp", ext_smdbltrp, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 494a036f6e..660f2eed5b 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -545,6 +545,7 @@ #define MSTATUS_SDT 0x01000000 /* Ssdbltrp extension */ #define MSTATUS_GVA 0x4000000000ULL #define MSTATUS_MPV 0x8000000000ULL +#define MSTATUS_MDT 0x200000000000ULL /* Smdbltrp extension */ #define MSTATUS64_UXL 0x0000000300000000ULL #define MSTATUS64_SXL 0x0000000C00000000ULL diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index a149c08167..cf6a802502 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -75,6 +75,7 @@ struct RISCVCPUConfig { bool ext_smstateen; bool ext_sstc; bool ext_ssdbltrp; + bool ext_smdbltrp; bool ext_svadu; bool ext_svinval; bool ext_svnapot; diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 3d747e5bfc..5ce0982f2f 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -1862,6 +1862,12 @@ void riscv_cpu_do_interrupt(CPUState *cs) s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE)); s = set_field(s, MSTATUS_MPP, env->priv); s = set_field(s, MSTATUS_MIE, 0); + if (riscv_cpu_cfg(env)->ext_smdbltrp) { + if (env->mstatus & MSTATUS_MDT) + cpu_abort(CPU(cpu), "M-mode double trap\n"); + + s = set_field(s, MSTATUS_MDT, 1); + } env->mstatus = s; env->mcause = cause | ~(((target_ulong)-1) >> async); if (smode_double_trap) { diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 1a2e739947..200b06e320 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1363,6 +1363,7 @@ static target_ulong legalize_mpp(CPURISCVState *env, target_ulong old_mpp, static RISCVException write_mstatus(CPURISCVState *env, int csrno, target_ulong val) { + const RISCVCPUConfig *cfg = riscv_cpu_cfg(env); uint64_t mstatus = env->mstatus; uint64_t mask = 0; RISCVMXL xl = riscv_cpu_mxl(env); @@ -1396,6 +1397,12 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, } } + if (cfg->ext_smdbltrp) { + mask |= MSTATUS_MDT; + if ((val & MSTATUS_MDT) != 0) + mask &= ~MSTATUS_MIE; + } + if (xl != MXL_RV32 || env->debugger) { if (riscv_has_ext(env, RVH)) { mask |= MSTATUS_MPV | MSTATUS_GVA; @@ -1434,6 +1441,11 @@ static RISCVException write_mstatush(CPURISCVState *env, int csrno, uint64_t valh = (uint64_t)val << 32; uint64_t mask = riscv_has_ext(env, RVH) ? MSTATUS_MPV | MSTATUS_GVA : 0; + if (riscv_cpu_cfg(env)->ext_smdbltrp) { + mask |= MSTATUS_MDT; + if ((val & MSTATUS_MDT) != 0) + mask |= MSTATUS_MIE; + } env->mstatus = (env->mstatus & ~mask) | (valh & mask); return RISCV_EXCP_NONE; diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 468ee58a00..d289d14237 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -354,6 +354,9 @@ target_ulong helper_mret(CPURISCVState *env) mstatus = set_field(mstatus, MSTATUS_MPP, riscv_has_ext(env, RVU) ? PRV_U : PRV_M); mstatus = set_field(mstatus, MSTATUS_MPV, 0); + if (riscv_cpu_cfg(env)->ext_smdbltrp) { + mstatus = set_field(mstatus, MSTATUS_MDT, 0); + } if ((env->priv_ver >= PRIV_VERSION_1_12_0) && (prev_priv != PRV_M)) { mstatus = set_field(mstatus, MSTATUS_MPRV, 0); }
The Smdbltrp extension allows to generate M-mode targeted double trap exceptions [1]. Such exceptions are generated if a trap is taken while mstatus.sdt is set to 1. The specification states that if the Smnrmi extension is implemented, then the hart enters a critical-error state and generate a critical-error signal. Since there is no Smrnmi support, the implementation generates a cpu abort. Link: https://github.com/riscv/riscv-double-trap/releases/download/v0.56/riscv-double-trap.pdf [1] Signed-off-by: Clément Léger <cleger@rivosinc.com> --- target/riscv/cpu.c | 5 +++++ target/riscv/cpu_bits.h | 1 + target/riscv/cpu_cfg.h | 1 + target/riscv/cpu_helper.c | 6 ++++++ target/riscv/csr.c | 12 ++++++++++++ target/riscv/op_helper.c | 3 +++ 6 files changed, 28 insertions(+)