diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2017-02-28 12:08:19 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-02-28 12:08:19 +0000 |
commit | aa488fe3bb5460c6675800ccd80f6dccbbd70159 (patch) | |
tree | 7bdaadadae7c270049e14f8fdca1a1abcdfba756 /hw/intc | |
parent | 39ae2474e337247e5930e8be783b689adc9f6215 (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')
-rw-r--r-- | hw/intc/armv7m_nvic.c | 12 |
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 */ |