diff mbox series

[v10,6/7] target/riscv: Add Zicfilp support for Smrnmi

Message ID 20241217062440.884261-7-frank.chang@sifive.com (mailing list archive)
State New
Headers show
Series Add Smrnmi support | expand

Commit Message

Frank Chang Dec. 17, 2024, 6:24 a.m. UTC
From: Frank Chang <frank.chang@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.chang@sifive.com>
---
 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(-)

Comments

Daniel Henrique Barboza Dec. 26, 2024, 12:53 p.m. UTC | #1
On 12/17/24 3:24 AM, frank.chang@sifive.com wrote:
> From: Frank Chang <frank.chang@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.chang@sifive.com>
> ---

Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

>   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;
>   }
>
diff mbox series

Patch

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;
 }