aboutsummaryrefslogtreecommitdiff
path: root/hw/intc/armv7m_nvic.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-02-28 12:08:19 +0000
committerPeter Maydell <peter.maydell@linaro.org>2017-02-28 12:08:19 +0000
commitaa488fe3bb5460c6675800ccd80f6dccbbd70159 (patch)
tree7bdaadadae7c270049e14f8fdca1a1abcdfba756 /hw/intc/armv7m_nvic.c
parent39ae2474e337247e5930e8be783b689adc9f6215 (diff)
armv7m: Check exception return consistency
Implement the exception return consistency checks described in the v7M pseudocode ExceptionReturn(). Inspired by a patch from Michael Davidsaver's series, but this is a reimplementation from scratch based on the ARM ARM pseudocode. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Diffstat (limited to 'hw/intc/armv7m_nvic.c')
-rw-r--r--hw/intc/armv7m_nvic.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 456480a3f2..718b1a1034 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -441,10 +441,11 @@ void armv7m_nvic_acknowledge_irq(void *opaque)
nvic_irq_update(s);
}
-void armv7m_nvic_complete_irq(void *opaque, int irq)
+int armv7m_nvic_complete_irq(void *opaque, int irq)
{
NVICState *s = (NVICState *)opaque;
VecInfo *vec;
+ int ret;
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
@@ -452,6 +453,13 @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
trace_nvic_complete_irq(irq);
+ if (!vec->active) {
+ /* Tell the caller this was an illegal exception return */
+ return -1;
+ }
+
+ ret = nvic_rettobase(s);
+
vec->active = 0;
if (vec->level) {
/* Re-pend the exception if it's still held high; only
@@ -462,6 +470,8 @@ void armv7m_nvic_complete_irq(void *opaque, int irq)
}
nvic_irq_update(s);
+
+ return ret;
}
/* callback when external interrupt line is changed */