When the Smsdbltrp ISA extension is enabled, if a trap happens while
MSTATUS.MDT is already set, it will trigger an abort or an NMI is the
Smrnmi extension is available.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
---
target/riscv/cpu_helper.c | 52 +++++++++++++++++++++++++--------------
1 file changed, 34 insertions(+), 18 deletions(-)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 623a3abbf7..8825572d5e 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1703,6 +1703,17 @@ static target_ulong riscv_transformed_insn(CPURISCVState *env,
return xinsn;
}
+static void riscv_do_nmi(CPURISCVState *env, target_ulong cause, bool virt)
+{
+ env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, false);
+ env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPV, virt);
+ env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPP, env->priv);
+ env->mncause = cause;
+ env->mnepc = env->pc;
+ env->pc = env->rnmi_irqvec;
+ riscv_cpu_set_mode(env, PRV_M, false);
+}
+
/*
* Handle Traps
*
@@ -1741,15 +1752,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
bool nnmi_excep = false;
if (cpu->cfg.ext_smrnmi && env->rnmip && async) {
- env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, false);
- env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPV,
- env->virt_enabled);
- env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPP,
- env->priv);
- env->mncause = cause | ((target_ulong)1U << (TARGET_LONG_BITS - 1));
- env->mnepc = env->pc;
- env->pc = env->rnmi_irqvec;
- riscv_cpu_set_mode(env, PRV_M, virt);
+ riscv_do_nmi(env, cause | ((target_ulong)1U << (TARGET_LONG_BITS - 1)),
+ virt);
return;
}
@@ -1932,11 +1936,32 @@ void riscv_cpu_do_interrupt(CPUState *cs)
/* Trapping to M mode, virt is disabled */
virt = false;
}
+ /*
+ * If the hart encounters an exception while executing in M-mode,
+ * with the mnstatus.NMIE bit clear, the program counter is set to
+ * the RNMI exception trap handler address.
+ */
+ nnmi_excep = cpu->cfg.ext_smrnmi &&
+ !get_field(env->mnstatus, MNSTATUS_NMIE) &&
+ !async;
s = env->mstatus;
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 (cpu->cfg.ext_smdbltrp) {
+ if (env->mstatus & MSTATUS_MDT) {
+ assert(env->priv == PRV_M);
+ if (!cpu->cfg.ext_smrnmi || nnmi_excep) {
+ cpu_abort(CPU(cpu), "M-mode double trap\n");
+ } else {
+ riscv_do_nmi(env, cause, false);
+ return;
+ }
+ }
+
+ s = set_field(s, MSTATUS_MDT, 1);
+ }
env->mstatus = s;
mxlen = 16 << riscv_cpu_mxl(env);
env->mcause = cause | ((target_ulong)async << (mxlen - 1));
@@ -1950,15 +1975,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
env->mtval = tval;
env->mtinst = tinst;
- /*
- * If the hart encounters an exception while executing in M-mode,
- * with the mnstatus.NMIE bit clear, the program counter is set to
- * the RNMI exception trap handler address.
- */
- nnmi_excep = cpu->cfg.ext_smrnmi &&
- !get_field(env->mnstatus, MNSTATUS_NMIE) &&
- !async;
-
if (nnmi_excep) {
env->pc = env->rnmi_excpvec;
} else {
--
2.45.2
On Fri, Oct 18, 2024 at 12:54 AM Clément Léger <cleger@rivosinc.com> wrote: > > When the Smsdbltrp ISA extension is enabled, if a trap happens while > MSTATUS.MDT is already set, it will trigger an abort or an NMI is the > Smrnmi extension is available. > > Signed-off-by: Clément Léger <cleger@rivosinc.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Alistair > --- > target/riscv/cpu_helper.c | 52 +++++++++++++++++++++++++-------------- > 1 file changed, 34 insertions(+), 18 deletions(-) > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c > index 623a3abbf7..8825572d5e 100644 > --- a/target/riscv/cpu_helper.c > +++ b/target/riscv/cpu_helper.c > @@ -1703,6 +1703,17 @@ static target_ulong riscv_transformed_insn(CPURISCVState *env, > return xinsn; > } > > +static void riscv_do_nmi(CPURISCVState *env, target_ulong cause, bool virt) > +{ > + env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, false); > + env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPV, virt); > + env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPP, env->priv); > + env->mncause = cause; > + env->mnepc = env->pc; > + env->pc = env->rnmi_irqvec; > + riscv_cpu_set_mode(env, PRV_M, false); > +} > + > /* > * Handle Traps > * > @@ -1741,15 +1752,8 @@ void riscv_cpu_do_interrupt(CPUState *cs) > bool nnmi_excep = false; > > if (cpu->cfg.ext_smrnmi && env->rnmip && async) { > - env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, false); > - env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPV, > - env->virt_enabled); > - env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPP, > - env->priv); > - env->mncause = cause | ((target_ulong)1U << (TARGET_LONG_BITS - 1)); > - env->mnepc = env->pc; > - env->pc = env->rnmi_irqvec; > - riscv_cpu_set_mode(env, PRV_M, virt); > + riscv_do_nmi(env, cause | ((target_ulong)1U << (TARGET_LONG_BITS - 1)), > + virt); > return; > } > > @@ -1932,11 +1936,32 @@ void riscv_cpu_do_interrupt(CPUState *cs) > /* Trapping to M mode, virt is disabled */ > virt = false; > } > + /* > + * If the hart encounters an exception while executing in M-mode, > + * with the mnstatus.NMIE bit clear, the program counter is set to > + * the RNMI exception trap handler address. > + */ > + nnmi_excep = cpu->cfg.ext_smrnmi && > + !get_field(env->mnstatus, MNSTATUS_NMIE) && > + !async; > > s = env->mstatus; > 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 (cpu->cfg.ext_smdbltrp) { > + if (env->mstatus & MSTATUS_MDT) { > + assert(env->priv == PRV_M); > + if (!cpu->cfg.ext_smrnmi || nnmi_excep) { > + cpu_abort(CPU(cpu), "M-mode double trap\n"); > + } else { > + riscv_do_nmi(env, cause, false); > + return; > + } > + } > + > + s = set_field(s, MSTATUS_MDT, 1); > + } > env->mstatus = s; > mxlen = 16 << riscv_cpu_mxl(env); > env->mcause = cause | ((target_ulong)async << (mxlen - 1)); > @@ -1950,15 +1975,6 @@ void riscv_cpu_do_interrupt(CPUState *cs) > env->mtval = tval; > env->mtinst = tinst; > > - /* > - * If the hart encounters an exception while executing in M-mode, > - * with the mnstatus.NMIE bit clear, the program counter is set to > - * the RNMI exception trap handler address. > - */ > - nnmi_excep = cpu->cfg.ext_smrnmi && > - !get_field(env->mnstatus, MNSTATUS_NMIE) && > - !async; > - > if (nnmi_excep) { > env->pc = env->rnmi_excpvec; > } else { > -- > 2.45.2 > >
© 2016 - 2024 Red Hat, Inc.