aboutsummaryrefslogtreecommitdiff
path: root/hw/intc
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-02-09 10:40:27 +0000
committerPeter Maydell <peter.maydell@linaro.org>2018-02-09 10:40:27 +0000
commit6c9485188170e11ad31ce477c8ce200b8e8ce59d (patch)
tree754d796a30a1467838d5766a9ad562c7d3b5ba14 /hw/intc
parent5ede82b8ccb652382c106d53f656ed67997d76e8 (diff)
downloadqemu-6c9485188170e11ad31ce477c8ce200b8e8ce59d.zip
qemu-6c9485188170e11ad31ce477c8ce200b8e8ce59d.tar.gz
qemu-6c9485188170e11ad31ce477c8ce200b8e8ce59d.tar.bz2
target/arm: Split "get pending exception info" from "acknowledge it"
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
Diffstat (limited to 'hw/intc')
-rw-r--r--hw/intc/armv7m_nvic.c30
-rw-r--r--hw/intc/trace-events3
2 files changed, 25 insertions, 8 deletions
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index b4a6e7c..360889d 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/hw/intc/trace-events b/hw/intc/trace-events
index 09e87d1..4092d28 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"