[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH 3/3] target/riscv: add Smdbltrp extension support
From: |
Clément Léger |
Subject: |
[RFC PATCH 3/3] target/riscv: add Smdbltrp extension support |
Date: |
Thu, 18 Apr 2024 15:39:15 +0200 |
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 */
#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