On Tue, Dec 31, 2024 at 1:28 PM <frank.ch...@sifive.com> wrote: > > From: Frank Chang <frank.ch...@sifive.com> > > Zicfilp extension introduces the MNPELP (bit 9) in mnstatus. > The MNPELP field holds the previous ELP. > > When a RNMI trap is delivered, the MNPELP is set to ELP and ELP set > to NO_LP_EXPECTED. Upon a mnret, if the mnstatus.MNPP holds the > value y, then ELP is set to the value of MNPELP if yLPE is 1; > otherwise, it is set to NO_LP_EXPECTED. > > Signed-off-by: Frank Chang <frank.ch...@sifive.com> > Reviewed-by: Daniel Henrique Barboza <dbarb...@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.fran...@wdc.com> Alistair > --- > target/riscv/cpu_bits.h | 1 + > target/riscv/cpu_helper.c | 11 ++++++++++- > target/riscv/op_helper.c | 9 +++++++++ > 3 files changed, 20 insertions(+), 1 deletion(-) > > diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h > index 17787fd693..be9d0f5c05 100644 > --- a/target/riscv/cpu_bits.h > +++ b/target/riscv/cpu_bits.h > @@ -643,6 +643,7 @@ typedef enum { > /* RNMI mnstatus CSR mask */ > #define MNSTATUS_NMIE 0x00000008 > #define MNSTATUS_MNPV 0x00000080 > +#define MNSTATUS_MNPELP 0x00000200 > #define MNSTATUS_MNPP 0x00001800 > > /* VM modes (satp.mode) privileged ISA 1.10 */ > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c > index e5ffbbbd83..1fb1e31031 100644 > --- a/target/riscv/cpu_helper.c > +++ b/target/riscv/cpu_helper.c > @@ -1918,6 +1918,10 @@ void riscv_cpu_do_interrupt(CPUState *cs) > env->mnepc = env->pc; > env->pc = env->rnmi_irqvec; > > + if (cpu_get_fcfien(env)) { > + env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPELP, > env->elp); > + } > + > /* Trapping to M mode, virt is disabled */ > riscv_cpu_set_mode(env, PRV_M, false); > > @@ -2085,7 +2089,12 @@ void riscv_cpu_do_interrupt(CPUState *cs) > /* handle the trap in M-mode */ > /* save elp status */ > if (cpu_get_fcfien(env)) { > - env->mstatus = set_field(env->mstatus, MSTATUS_MPELP, env->elp); > + if (nnmi_excep) { > + env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPELP, > + env->elp); > + } else { > + env->mstatus = set_field(env->mstatus, MSTATUS_MPELP, > env->elp); > + } > } > > if (riscv_has_ext(env, RVH)) { > diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c > index 63ec53e992..a4b625fcd9 100644 > --- a/target/riscv/op_helper.c > +++ b/target/riscv/op_helper.c > @@ -402,6 +402,15 @@ target_ulong helper_mnret(CPURISCVState *env) > > riscv_cpu_set_mode(env, prev_priv, prev_virt); > > + /* > + * If forward cfi enabled for new priv, restore elp status > + * and clear mnpelp in mnstatus > + */ > + if (cpu_get_fcfien(env)) { > + env->elp = get_field(env->mnstatus, MNSTATUS_MNPELP); > + } > + env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPELP, 0); > + > return retpc; > } > > -- > 2.34.1 > >