@@ -642,6 +642,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 */
@@ -1863,6 +1863,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);
@@ -2030,7 +2034,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)) {
@@ -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;
}