qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 02/30] target/arm: Split "get pending exception info" from "acknowledge it"
Date: Fri,  9 Feb 2018 11:02:46 +0000	[thread overview]
Message-ID: <20180209110314.11766-3-peter.maydell@linaro.org> (raw)
In-Reply-To: <20180209110314.11766-1-peter.maydell@linaro.org>

Currently armv7m_nvic_acknowledge_irq() does three things:
 * make the current highest priority pending interrupt active
 * return a bool indicating whether that interrupt is targeting
   Secure or NonSecure state
 * implicitly tell the caller which is the highest priority
   pending interrupt by setting env->v7m.exception

We need to split these jobs, because v7m_exception_taken()
needs to know whether the pending interrupt targets Secure so
it can choose to stack callee-saves registers or not, but it
must not make the interrupt active until after it has done
that stacking, in case the stacking causes a derived exception.
Similarly, it needs to know the number of the pending interrupt
so it can read the correct vector table entry before the
interrupt is made active, because vector table reads might
also cause a derived exception.

Create a new armv7m_nvic_get_pending_irq_info() function which simply
returns information about the highest priority pending interrupt, and
use it to rearrange the v7m_exception_taken() code so we don't
acknowledge the exception until we've done all the things which could
possibly cause a derived exception.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 1517324542-6607-3-git-send-email-peter.maydell@linaro.org
---
 target/arm/cpu.h      | 19 ++++++++++++++++---
 hw/intc/armv7m_nvic.c | 30 +++++++++++++++++++++++-------
 target/arm/helper.c   | 16 ++++++++++++----
 hw/intc/trace-events  |  3 ++-
 4 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index b3d4da3048..3533bb8e9a 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1518,6 +1518,21 @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure);
  * a different exception).
  */
 void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
+/**
+ * armv7m_nvic_get_pending_irq_info: return highest priority pending
+ *    exception, and whether it targets Secure state
+ * @opaque: the NVIC
+ * @pirq: set to pending exception number
+ * @ptargets_secure: set to whether pending exception targets Secure
+ *
+ * This function writes the number of the highest priority pending
+ * exception (the one which would be made active by
+ * armv7m_nvic_acknowledge_irq()) to @pirq, and sets @ptargets_secure
+ * to true if the current highest priority pending exception should
+ * be taken to Secure state, false for NS.
+ */
+void armv7m_nvic_get_pending_irq_info(void *opaque, int *pirq,
+                                      bool *ptargets_secure);
 /**
  * armv7m_nvic_acknowledge_irq: make highest priority pending exception active
  * @opaque: the NVIC
@@ -1525,10 +1540,8 @@ void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
  * Move the current highest priority pending exception from the pending
  * state to the active state, and update v7m.exception to indicate that
  * it is the exception currently being handled.
- *
- * Returns: true if exception should be taken to Secure state, false for NS
  */
-bool armv7m_nvic_acknowledge_irq(void *opaque);
+void armv7m_nvic_acknowledge_irq(void *opaque);
 /**
  * armv7m_nvic_complete_irq: complete specified interrupt or exception
  * @opaque: the NVIC
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index b4a6e7c62e..360889d30b 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -650,24 +650,20 @@ void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure)
 }
 
 /* Make pending IRQ active.  */
-bool armv7m_nvic_acknowledge_irq(void *opaque)
+void armv7m_nvic_acknowledge_irq(void *opaque)
 {
     NVICState *s = (NVICState *)opaque;
     CPUARMState *env = &s->cpu->env;
     const int pending = s->vectpending;
     const int running = nvic_exec_prio(s);
     VecInfo *vec;
-    bool targets_secure;
 
     assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
 
     if (s->vectpending_is_s_banked) {
         vec = &s->sec_vectors[pending];
-        targets_secure = true;
     } else {
         vec = &s->vectors[pending];
-        targets_secure = !exc_is_banked(s->vectpending) &&
-            exc_targets_secure(s, s->vectpending);
     }
 
     assert(vec->enabled);
@@ -675,7 +671,7 @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
 
     assert(s->vectpending_prio < running);
 
-    trace_nvic_acknowledge_irq(pending, s->vectpending_prio, targets_secure);
+    trace_nvic_acknowledge_irq(pending, s->vectpending_prio);
 
     vec->active = 1;
     vec->pending = 0;
@@ -683,8 +679,28 @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
     write_v7m_exception(env, s->vectpending);
 
     nvic_irq_update(s);
+}
+
+void armv7m_nvic_get_pending_irq_info(void *opaque,
+                                      int *pirq, bool *ptargets_secure)
+{
+    NVICState *s = (NVICState *)opaque;
+    const int pending = s->vectpending;
+    bool targets_secure;
+
+    assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
+
+    if (s->vectpending_is_s_banked) {
+        targets_secure = true;
+    } else {
+        targets_secure = !exc_is_banked(pending) &&
+            exc_targets_secure(s, pending);
+    }
+
+    trace_nvic_get_pending_irq_info(pending, targets_secure);
 
-    return targets_secure;
+    *ptargets_secure = targets_secure;
+    *pirq = pending;
 }
 
 int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index bfce09643b..6062f380d4 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6395,12 +6395,12 @@ static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
     }
 }
 
-static uint32_t arm_v7m_load_vector(ARMCPU *cpu, bool targets_secure)
+static uint32_t arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure)
 {
     CPUState *cs = CPU(cpu);
     CPUARMState *env = &cpu->env;
     MemTxResult result;
-    hwaddr vec = env->v7m.vecbase[targets_secure] + env->v7m.exception * 4;
+    hwaddr vec = env->v7m.vecbase[targets_secure] + exc * 4;
     uint32_t addr;
 
     addr = address_space_ldl(cs->as, vec,
@@ -6462,8 +6462,9 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
     CPUARMState *env = &cpu->env;
     uint32_t addr;
     bool targets_secure;
+    int exc;
 
-    targets_secure = armv7m_nvic_acknowledge_irq(env->nvic);
+    armv7m_nvic_get_pending_irq_info(env->nvic, &exc, &targets_secure);
 
     if (arm_feature(env, ARM_FEATURE_V8)) {
         if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
@@ -6531,6 +6532,14 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
         }
     }
 
+    addr = arm_v7m_load_vector(cpu, exc, targets_secure);
+
+    /* Now we've done everything that might cause a derived exception
+     * we can go ahead and activate whichever exception we're going to
+     * take (which might now be the derived exception).
+     */
+    armv7m_nvic_acknowledge_irq(env->nvic);
+
     /* Switch to target security state -- must do this before writing SPSEL */
     switch_v7m_security_state(env, targets_secure);
     write_v7m_control_spsel(env, 0);
@@ -6538,7 +6547,6 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain)
     /* Clear IT bits */
     env->condexec_bits = 0;
     env->regs[14] = lr;
-    addr = arm_v7m_load_vector(cpu, targets_secure);
     env->regs[15] = addr & 0xfffffffe;
     env->thumb = addr & 1;
 }
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 09e87d14bd..4092d2825e 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -180,7 +180,8 @@ nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled"
 nvic_set_pending(int irq, bool secure, bool derived, int en, int prio) "NVIC set pending irq %d secure-bank %d derived %d (enabled: %d priority %d)"
 nvic_clear_pending(int irq, bool secure, int en, int prio) "NVIC clear pending irq %d secure-bank %d (enabled: %d priority %d)"
 nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1"
-nvic_acknowledge_irq(int irq, int prio, bool targets_secure) "NVIC acknowledge IRQ: %d now active (prio %d targets_secure %d)"
+nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (prio %d)"
+nvic_get_pending_irq_info(int irq, bool secure) "NVIC next IRQ %d: targets_secure: %d"
 nvic_complete_irq(int irq, bool secure) "NVIC complete IRQ %d (secure %d)"
 nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
 nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
-- 
2.16.1

  parent reply	other threads:[~2018-02-09 11:03 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-09 11:02 [Qemu-devel] [PULL 00/30] target-arm queue Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 01/30] target/arm: Add armv7m_nvic_set_pending_derived() Peter Maydell
2018-02-09 11:02 ` Peter Maydell [this message]
2018-02-09 11:02 ` [Qemu-devel] [PULL 03/30] target/arm: Add ignore_stackfaults argument to v7m_exception_taken() Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 04/30] target/arm: Make v7M exception entry stack push check MPU Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 05/30] target/arm: Make v7m_push_callee_stack() honour MPU Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 06/30] target/arm: Make exception vector loads honour the SAU Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 07/30] target/arm: Handle exceptions during exception stack pop Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 08/30] target/arm: implement SHA-512 instructions Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 09/30] target/arm: implement SHA-3 instructions Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 10/30] target/arm: implement SM3 instructions Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 11/30] target/arm: implement SM4 instructions Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 12/30] target/arm: enable user-mode SHA-3, SM3, SM4 and SHA-512 instruction support Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 13/30] sdhci: Add i.MX specific subtype of SDHCI Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 14/30] hw: i.MX: Convert i.MX6 to use TYPE_IMX_USDHC Peter Maydell
2018-02-09 11:02 ` [Qemu-devel] [PULL 15/30] i.MX: Add code to emulate i.MX7 CCM, PMU and ANALOG IP blocks Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 16/30] i.MX: Add code to emulate i.MX2 watchdog IP block Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 17/30] i.MX: Add code to emulate i.MX7 SNVS IP-block Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 18/30] i.MX: Add code to emulate GPCv2 IP block Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 19/30] i.MX: Add i.MX7 GPT variant Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 20/30] i.MX: Add implementation of i.MX7 GPR IP block Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 21/30] usb: Add basic code to emulate Chipidea USB IP Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 22/30] hw/arm: Move virt's PSCI DT fixup code to arm/boot.c Peter Maydell
2018-03-27 14:22   ` [Qemu-devel] [PULL, " Marc Zyngier
2018-02-09 11:03 ` [Qemu-devel] [PULL 23/30] target/arm: Expand vector registers for SVE Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 24/30] target/arm: Add predicate " Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 25/30] target/arm: Add SVE to migration state Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 26/30] target/arm: Add ZCR_ELx Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 27/30] target/arm: Add SVE state to TB->FLAGS Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 28/30] target/arm/kvm: gic: Prevent creating userspace GICv3 with KVM Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 29/30] target/arm/translate.c: Fix missing 'break' for TT insns Peter Maydell
2018-02-09 11:03 ` [Qemu-devel] [PULL 30/30] hw/core/generic-loader: Allow PC to be set on command line Peter Maydell
2018-02-09 14:38 ` [Qemu-devel] [PULL 00/30] target-arm queue Peter Maydell

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=20180209110314.11766-3-peter.maydell@linaro.org \
    --to=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).