All of lore.kernel.org
 help / color / mirror / Atom feed
From: frank.chang@sifive.com
To: qemu-devel@nongnu.org, qemu-riscv@nongnu.org
Cc: Frank Chang <frank.chang@sifive.com>,
	Alistair Francis <Alistair.Francis@wdc.com>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	Sagar Karandikar <sagark@eecs.berkeley.edu>,
	Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Subject: [RFC v2 3/4] target/riscv: handle RNMI interrupt and exception
Date: Thu,  1 Apr 2021 17:26:50 +0800	[thread overview]
Message-ID: <20210401092659.12014-4-frank.chang@sifive.com> (raw)
In-Reply-To: <20210401092659.12014-1-frank.chang@sifive.com>

From: Frank Chang <frank.chang@sifive.com>

Signed-off-by: Frank Chang <frank.chang@sifive.com>
---
 target/riscv/cpu_bits.h   |  4 ++++
 target/riscv/cpu_helper.c | 49 +++++++++++++++++++++++++++++++++++----
 2 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index a376ede0cc5..937b1f28455 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -607,4 +607,8 @@
 #define MIE_UTIE                           (1 << IRQ_U_TIMER)
 #define MIE_SSIE                           (1 << IRQ_S_SOFT)
 #define MIE_USIE                           (1 << IRQ_U_SOFT)
+
+/* RISC-V-specific interrupt pending bits. */
+#define CPU_INTERRUPT_RNMI                 CPU_INTERRUPT_TGT_EXT_0
+
 #endif
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 21c54ef5613..67a633154a9 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -38,6 +38,19 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 #ifndef CONFIG_USER_ONLY
 static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 {
+    if (riscv_feature(env, RISCV_FEATURE_RNMI)) {
+        /* Priority: RNMI > Other interrupt. */
+        if (env->nmip && env->nmie) {
+            return ctz64(env->nmip); /* since non-zero */
+        } else if (!env->nmie) {
+            /*
+             * We are already in RNMI handler,
+             * other interrupts cannot preempt.
+             */
+            return EXCP_NONE;
+        }
+    }
+
     target_ulong irqs;
 
     target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
@@ -80,7 +93,9 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 {
 #if !defined(CONFIG_USER_ONLY)
-    if (interrupt_request & CPU_INTERRUPT_HARD) {
+    uint32_t mask = CPU_INTERRUPT_HARD | CPU_INTERRUPT_RNMI;
+
+    if (interrupt_request & mask) {
         RISCVCPU *cpu = RISCV_CPU(cs);
         CPURISCVState *env = &cpu->env;
         int interruptno = riscv_cpu_local_irq_pending(env);
@@ -909,6 +924,23 @@ void riscv_cpu_do_interrupt(CPUState *cs)
     target_ulong tval = 0;
     target_ulong htval = 0;
     target_ulong mtval2 = 0;
+    target_ulong nextpc;
+    bool nmi_execp = false;
+
+    if (riscv_feature(env, RISCV_FEATURE_RNMI)) {
+        nmi_execp = !env->nmie && !async;
+
+        if (env->nmip && async) {
+            env->nmie = false;
+            env->mnstatus = set_field(env->mnstatus, MSTATUS_MPP,
+                                      env->priv);
+            env->mncause = cause;
+            env->mnepc = env->pc;
+            env->pc = env->rnmi_irqvec;
+            riscv_cpu_set_mode(env, PRV_M);
+            goto handled;
+        }
+    }
 
     if  (cause == RISCV_EXCP_SEMIHOST) {
         if (env->priv >= PRV_S) {
@@ -967,7 +999,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
                   __func__, env->mhartid, async, cause, env->pc, tval,
                   riscv_cpu_get_trap_name(cause, async));
 
-    if (env->priv <= PRV_S &&
+    if (env->priv <= PRV_S && !nmi_execp &&
             cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
         /* handle the trap in S-mode */
         if (riscv_has_ext(env, RVH)) {
@@ -1056,8 +1088,15 @@ void riscv_cpu_do_interrupt(CPUState *cs)
         env->mepc = env->pc;
         env->mbadaddr = tval;
         env->mtval2 = mtval2;
-        env->pc = (env->mtvec >> 2 << 2) +
-            ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
+
+        if (nmi_execp) {
+            nextpc = env->rnmi_excpvec;
+        } else {
+            nextpc = (env->mtvec >> 2 << 2) +
+                ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
+        }
+        env->pc = nextpc;
+
         riscv_cpu_set_mode(env, PRV_M);
     }
 
@@ -1068,6 +1107,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
      */
 
     env->two_stage_lookup = false;
+
+handled:
 #endif
     cs->exception_index = EXCP_NONE; /* mark handled to qemu */
 }
-- 
2.17.1



WARNING: multiple messages have this Message-ID (diff)
From: frank.chang@sifive.com
To: qemu-devel@nongnu.org, qemu-riscv@nongnu.org
Cc: Frank Chang <frank.chang@sifive.com>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	Alistair Francis <Alistair.Francis@wdc.com>,
	Sagar Karandikar <sagark@eecs.berkeley.edu>,
	Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Subject: [RFC v2 3/4] target/riscv: handle RNMI interrupt and exception
Date: Thu,  1 Apr 2021 17:26:50 +0800	[thread overview]
Message-ID: <20210401092659.12014-4-frank.chang@sifive.com> (raw)
In-Reply-To: <20210401092659.12014-1-frank.chang@sifive.com>

From: Frank Chang <frank.chang@sifive.com>

Signed-off-by: Frank Chang <frank.chang@sifive.com>
---
 target/riscv/cpu_bits.h   |  4 ++++
 target/riscv/cpu_helper.c | 49 +++++++++++++++++++++++++++++++++++----
 2 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index a376ede0cc5..937b1f28455 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -607,4 +607,8 @@
 #define MIE_UTIE                           (1 << IRQ_U_TIMER)
 #define MIE_SSIE                           (1 << IRQ_S_SOFT)
 #define MIE_USIE                           (1 << IRQ_U_SOFT)
+
+/* RISC-V-specific interrupt pending bits. */
+#define CPU_INTERRUPT_RNMI                 CPU_INTERRUPT_TGT_EXT_0
+
 #endif
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 21c54ef5613..67a633154a9 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -38,6 +38,19 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 #ifndef CONFIG_USER_ONLY
 static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 {
+    if (riscv_feature(env, RISCV_FEATURE_RNMI)) {
+        /* Priority: RNMI > Other interrupt. */
+        if (env->nmip && env->nmie) {
+            return ctz64(env->nmip); /* since non-zero */
+        } else if (!env->nmie) {
+            /*
+             * We are already in RNMI handler,
+             * other interrupts cannot preempt.
+             */
+            return EXCP_NONE;
+        }
+    }
+
     target_ulong irqs;
 
     target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
@@ -80,7 +93,9 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 {
 #if !defined(CONFIG_USER_ONLY)
-    if (interrupt_request & CPU_INTERRUPT_HARD) {
+    uint32_t mask = CPU_INTERRUPT_HARD | CPU_INTERRUPT_RNMI;
+
+    if (interrupt_request & mask) {
         RISCVCPU *cpu = RISCV_CPU(cs);
         CPURISCVState *env = &cpu->env;
         int interruptno = riscv_cpu_local_irq_pending(env);
@@ -909,6 +924,23 @@ void riscv_cpu_do_interrupt(CPUState *cs)
     target_ulong tval = 0;
     target_ulong htval = 0;
     target_ulong mtval2 = 0;
+    target_ulong nextpc;
+    bool nmi_execp = false;
+
+    if (riscv_feature(env, RISCV_FEATURE_RNMI)) {
+        nmi_execp = !env->nmie && !async;
+
+        if (env->nmip && async) {
+            env->nmie = false;
+            env->mnstatus = set_field(env->mnstatus, MSTATUS_MPP,
+                                      env->priv);
+            env->mncause = cause;
+            env->mnepc = env->pc;
+            env->pc = env->rnmi_irqvec;
+            riscv_cpu_set_mode(env, PRV_M);
+            goto handled;
+        }
+    }
 
     if  (cause == RISCV_EXCP_SEMIHOST) {
         if (env->priv >= PRV_S) {
@@ -967,7 +999,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
                   __func__, env->mhartid, async, cause, env->pc, tval,
                   riscv_cpu_get_trap_name(cause, async));
 
-    if (env->priv <= PRV_S &&
+    if (env->priv <= PRV_S && !nmi_execp &&
             cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
         /* handle the trap in S-mode */
         if (riscv_has_ext(env, RVH)) {
@@ -1056,8 +1088,15 @@ void riscv_cpu_do_interrupt(CPUState *cs)
         env->mepc = env->pc;
         env->mbadaddr = tval;
         env->mtval2 = mtval2;
-        env->pc = (env->mtvec >> 2 << 2) +
-            ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
+
+        if (nmi_execp) {
+            nextpc = env->rnmi_excpvec;
+        } else {
+            nextpc = (env->mtvec >> 2 << 2) +
+                ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
+        }
+        env->pc = nextpc;
+
         riscv_cpu_set_mode(env, PRV_M);
     }
 
@@ -1068,6 +1107,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
      */
 
     env->two_stage_lookup = false;
+
+handled:
 #endif
     cs->exception_index = EXCP_NONE; /* mark handled to qemu */
 }
-- 
2.17.1



  parent reply	other threads:[~2021-04-01  9:31 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-01  9:26 [RFC v2 0/4] target/riscv: add RNMI support frank.chang
2021-04-01  9:26 ` [RFC v2 1/4] target/riscv: add RNMI cpu feature frank.chang
2021-04-01  9:26   ` frank.chang
2021-04-01  9:26 ` [RFC v2 2/4] target/riscv: add RNMI CSRs frank.chang
2021-04-01  9:26   ` frank.chang
2021-04-01  9:26 ` frank.chang [this message]
2021-04-01  9:26   ` [RFC v2 3/4] target/riscv: handle RNMI interrupt and exception frank.chang
2021-04-01  9:26 ` [RFC v2 4/4] target/riscv: add RNMI mnret instruction frank.chang
2021-04-01  9:26   ` frank.chang
2021-04-01  9:36 ` [RFC v2 0/4] target/riscv: add RNMI support Frank Chang
2021-04-01  9:36   ` Frank Chang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210401092659.12014-4-frank.chang@sifive.com \
    --to=frank.chang@sifive.com \
    --cc=Alistair.Francis@wdc.com \
    --cc=kbastian@mail.uni-paderborn.de \
    --cc=palmer@dabbelt.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-riscv@nongnu.org \
    --cc=sagark@eecs.berkeley.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.